CONTAINER: winx64
PLATFORM: 'x64'
ARCHITECTURE: 'x86_amd64'
- GENERATOR: '"Visual Studio 16 2019" -A x64'
+ GENERATOR: '"Visual Studio 17 2022" -A x64'
container: $[ variables['CONTAINER'] ]
timeoutInMinutes: 0
variables:
# find the commit hash on a quick non-forced update too
fetchDepth: 10
- script: |
- brew install cmake pkg-config boost eigen flann glew libusb qhull vtk glew freeglut qt5 libpcap libomp suite-sparse zlib google-benchmark cjson
+ brew install cmake pkg-config boost eigen flann nanoflann glew libusb qhull vtk glew freeglut qt5 libpcap libomp suite-sparse zlib google-benchmark cjson
brew install brewsci/science/openni
git clone https://github.com/abseil/googletest.git $GOOGLE_TEST_DIR # the official endpoint changed to abseil/googletest
cd $GOOGLE_TEST_DIR && git checkout release-1.8.1
- job: documentation
displayName: Generate Documentation
pool:
- vmImage: 'Ubuntu 20.04'
+ vmImage: 'ubuntu-22.04'
container: doc
variables:
BUILD_DIR: '$(Agent.BuildDirectory)/build'
-DCMAKE_BUILD_TYPE="Release" \
-DPCL_ONLY_CORE_POINT_TYPES=ON \
-DBUILD_io:BOOL=OFF \
- -DBUILD_kdtree:BOOL=OFF && \
+ -DBUILD_kdtree:BOOL=OFF $([ $(TAG) = "20.04" ] && (echo " -DCMAKE_CXX_STANDARD=14 -DCMAKE_CUDA_STANDARD=14")) && \
cmake --build . -- -j2'
displayName: 'Verify Dockerimage'
- task: Docker@2
condition: and(eq(variables['Build.Repository.Name'], 'PointCloudLibrary/pcl'),
eq(variables['Build.SourceBranch'], 'refs/heads/master'))
- job: BuildAndPushWindows
- timeoutInMinutes: 360
+ timeoutInMinutes: 380
displayName: "Env"
pool:
vmImage: 'windows-2022'
TAG: windows2022-x86
GENERATOR: "'Visual Studio 16 2019' -A Win32"
VCPKGCOMMIT: f7423ee180c4b7f40d43402c2feb3859161ef625
+ CHANNEL_BASE_URL: "https://aka.ms/vs/16/release"
Winx64:
PLATFORM: x64
TAG: windows2022-x64
- GENERATOR: "'Visual Studio 16 2019' -A x64"
+ GENERATOR: "'Visual Studio 17 2022' -A x64"
VCPKGCOMMIT: master
+ CHANNEL_BASE_URL: "https://aka.ms/vs/17/release"
steps:
- task: Docker@2
displayName: "Build docker image"
--no-cache
--build-arg PLATFORM=$(PLATFORM)
--build-arg VCPKGCOMMIT=$(VCPKGCOMMIT)
+ --build-arg CHANNEL_BASE_URL=$(CHANNEL_BASE_URL)
-t $(dockerHubID)/env:$(TAG)
dockerfile: '$(Build.SourcesDirectory)/.dev/docker/windows/Dockerfile'
tags: "$(TAG)"
- checkout: self
# find the commit hash on a quick non-forced update too
fetchDepth: 10
- - script: ./.dev/format.sh $(which clang-format) .
+ - script: python ./.dev/format.py .
displayName: 'Run clang-format'
- script: git diff > formatting.patch
displayName: 'Compute diff'
- job: tutorials
displayName: Building Tutorials
pool:
- vmImage: 'Ubuntu 20.04'
+ vmImage: 'ubuntu-22.04'
container: env2204
timeoutInMinutes: 0
variables:
POSSIBLE_VTK_VERSION=("9") \
POSSIBLE_CMAKE_CXX_STANDARD=("14" "17" "20" "23") \
POSSIBLE_CMAKE_BUILD_TYPE=("None" "Debug" "Release" "RelWithDebInfo" "MinSizeRel") \
- POSSIBLE_COMPILER_PACKAGE=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "clang libomp-dev" "clang-14 libomp-14-dev" "clang-15 libomp-15-dev" "clang-16 libomp-16-dev" "clang-17 libomp-17-dev" "clang-18 libomp-18-dev" "clang-19 libomp-19-dev") \
- POSSIBLE_CMAKE_C_COMPILER=("gcc" "gcc-11" "gcc-12" "gcc-13" "gcc-14" "clang" "clang-14" "clang-15" "clang-16" "clang-17" "clang-18" "clang-19") \
- POSSIBLE_CMAKE_CXX_COMPILER=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "clang++" "clang++-14" "clang++-15" "clang++-16" "clang++-17" "clang++-18" "clang++-19") \
+ POSSIBLE_COMPILER_PACKAGE=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "g++-15" "clang libomp-dev" "clang-14 libomp-14-dev" "clang-15 libomp-15-dev" "clang-17 libomp-17-dev" "clang-18 libomp-18-dev" "clang-19 libomp-19-dev" "clang-20 libomp-20-dev") \
+ POSSIBLE_CMAKE_C_COMPILER=("gcc" "gcc-11" "gcc-12" "gcc-13" "gcc-14" "gcc-15" "clang" "clang-14" "clang-15" "clang-17" "clang-18" "clang-19" "clang-20") \
+ POSSIBLE_CMAKE_CXX_COMPILER=("g++" "g++-11" "g++-12" "g++-13" "g++-14" "g++-15" "clang++" "clang++-14" "clang++-15" "clang++-17" "clang++-18" "clang++-19" "clang++-20") \
CHOSEN_COMPILER=$[RANDOM%${#POSSIBLE_COMPILER_PACKAGE[@]}] \
dockerBuildArgs="--build-arg VTK_VERSION=${POSSIBLE_VTK_VERSION[$[RANDOM%${#POSSIBLE_VTK_VERSION[@]}]]} --build-arg CMAKE_CXX_STANDARD=${POSSIBLE_CMAKE_CXX_STANDARD[$[RANDOM%${#POSSIBLE_CMAKE_CXX_STANDARD[@]}]]} --build-arg CMAKE_BUILD_TYPE=${POSSIBLE_CMAKE_BUILD_TYPE[$[RANDOM%${#POSSIBLE_CMAKE_BUILD_TYPE[@]}]]} --build-arg COMPILER_PACKAGE=\"${POSSIBLE_COMPILER_PACKAGE[$CHOSEN_COMPILER]}\" --build-arg CMAKE_C_COMPILER=${POSSIBLE_CMAKE_C_COMPILER[$CHOSEN_COMPILER]} --build-arg CMAKE_CXX_COMPILER=${POSSIBLE_CMAKE_CXX_COMPILER[$CHOSEN_COMPILER]}" ; \
echo "##vso[task.setvariable variable=dockerBuildArgs]$dockerBuildArgs"
ARG ENSENSOSDK_VERSION=3.2.489
# See https://github.com/IntelRealSense/librealsense/tags for available tags of releases
-ARG REALSENSE_VERSION=2.50.0
+ARG REALSENSE_VERSION=2.56.3
# Check https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=libvtk%20qt-dev
# for available packages for chosen UBUNTU_VERSION
build-essential \
clang \
clang-tidy \
+ git \
libbenchmark-dev \
libblas-dev \
libboost-serialization-dev \
software-properties-common \
wget \
xvfb \
+ && if dpkg --compare-versions $(lsb_release -sr) ge 22.04; then \
+ apt-get -V install -y libnanoflann-dev ; \
+ fi \
&& if [ "$USE_LATEST_CMAKE" = true ] ; then \
cmake_ubuntu_version=$(lsb_release -cs) ; \
if ! wget -q --method=HEAD "https://apt.kitware.com/ubuntu/dists/$cmake_ubuntu_version/Release"; then \
libboost-filesystem-dev \
libboost-iostreams-dev \
libboost-system-dev \
+ libcjson-dev \
libeigen3-dev \
libflann-dev \
libglew-dev \
"C:\TEMP\VisualStudio.chman", `
"--add", `
"Microsoft.VisualStudio.Workload.VCTools", `
- "Microsoft.Net.Component.4.8.SDK", `
+ "Microsoft.Net.Component.4.7.2.SDK", `
+ "Microsoft.Net.Component.4.7.2.TargetingPack", `
"Microsoft.VisualStudio.Component.VC.ATLMFC", `
"--includeRecommended" `
-Wait -PassThru; `
boost-uuid `
boost-cmake `
flann `
+ nanoflann `
eigen3 `
qhull `
glew `
freeglut `
- vtk[qt,opengl] `
+ vtk[core,qt,opengl] `
gtest `
benchmark `
openni2 `
--- /dev/null
+#!/usr/bin/env python3
+
+import os
+import sys
+import subprocess
+import argparse
+
+EXTENSIONS = (".c", ".h", ".cpp", ".hpp", ".cxx", ".hxx", ".cu")
+WHITELIST_FILE = os.path.join(".dev", "whitelist.txt")
+
+def load_whitelist():
+ if not os.path.isfile(WHITELIST_FILE):
+ print(f"Could not find whitelist file at {WHITELIST_FILE}")
+ sys.exit(167)
+ with open(WHITELIST_FILE, "r") as f:
+ return [line.strip() for line in f if line.strip()]
+
+def is_in_whitelist(file_path, whitelist):
+ file_path = os.path.normpath(file_path)
+ for w in whitelist:
+ w_norm = os.path.normpath(w)
+ if os.path.commonpath([file_path, w_norm]) == w_norm or file_path.startswith(w_norm + os.sep):
+ return True
+ return False
+
+def find_files(path):
+ if os.path.isfile(path):
+ if path.endswith(EXTENSIONS):
+ yield path
+ elif os.path.isdir(path):
+ for root, _, files in os.walk(path):
+ for file in files:
+ if file.endswith(EXTENSIONS):
+ yield os.path.join(root, file)
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Format C/C++/CUDA files using clang-format via pipx."
+ )
+ parser.add_argument(
+ "files",
+ nargs="+",
+ help="List of files to check/format, or a single '.' to check all whitelisted files."
+ )
+ args = parser.parse_args()
+
+ whitelist = load_whitelist()
+ manual_mode = len(args.files) == 1 and args.files[0] == "."
+
+ if manual_mode:
+ all_files = []
+ for rel_path in whitelist:
+ abs_path = os.path.join(os.getcwd(), rel_path)
+ all_files.extend(find_files(abs_path))
+ else:
+ all_files = [
+ f for f in args.files
+ if f.endswith(EXTENSIONS) and os.path.isfile(f) and is_in_whitelist(f, whitelist)
+ ]
+
+ all_files = list(set(all_files)) # Remove duplicates
+
+ if not all_files:
+ print("No files found to format.")
+ sys.exit(0)
+
+ check_cmd = ["pipx", "run", "clang-format==14.0.3", "--dry-run", "--Werror", "--style=file"] + all_files
+ result = subprocess.run(check_cmd, capture_output=True, text=True)
+ if result.returncode != 0:
+ format_cmd = ["pipx", "run", "clang-format==14.0.3", "-i", "--style=file"] + all_files
+ subprocess.run(format_cmd)
+ if not manual_mode:
+ sys.exit(1) # Only fail for pre-commit
+ # In manual mode, just continue and exit 0
+
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
# $ sh /pcl/format.sh `which clang-format` /pcl
format() {
- # don't use a directory with whitespace
- local whitelist="apps/3d_rec_framework apps/in_hand_scanner apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers gpu/segmentation"
-
local PCL_DIR="${2}"
local formatter="${1}"
exit 166
fi
- # check for self
if [ ! -f "${PCL_DIR}/.dev/format.sh" ]; then
echo "Please ensure that PCL_SOURCE_DIR is passed as the second argument"
exit 166
fi
- for dir in ${whitelist}; do
+ local whitelist_file="${PCL_DIR}/.dev/whitelist.txt"
+ if [ ! -f "${whitelist_file}" ]; then
+ echo "Could not find whitelist file at ${whitelist_file}"
+ exit 167
+ fi
+
+ while IFS= read -r dir || [ -n "$dir" ]; do
+ [ -z "$dir" ] && continue
path=${PCL_DIR}/${dir}
- find ${path} -type f -iname *.[ch] -o -iname *.[ch]pp -o -iname *.[ch]xx \
- -iname *.cu | xargs -n1 ${formatter} -i -style=file
- done
+ find ${path} -type f \( -iname "*.[ch]" -o -iname "*.[ch]pp" -o -iname "*.[ch]xx" -o -iname "*.cu" \) | xargs -n1 ${formatter} -i -style=file
+ done < "${whitelist_file}"
}
-format $@
+format "$@"
--- /dev/null
+apps/cloud_composer/include/pcl/apps/cloud_composer
+apps/cloud_composer/src/point_selectors
+apps/cloud_composer/src/tool_interface
+apps/cloud_composer/tools
+apps/cloud_composer/src/cloud_composer.cpp
+apps/cloud_composer/src/cloud_viewer.cpp
+apps/cloud_composer/src/commands.cpp
+apps/cloud_composer/src/item_inspector.cpp
+apps/cloud_composer/src/items/cloud_composer_item.cpp
+apps/cloud_composer/src/items/fpfh_item.cpp
+apps/cloud_composer/src/main.cpp
+apps/cloud_composer/src/merge_selection.cpp
+apps/cloud_composer/src/properties_model.cpp
+apps/cloud_composer/src/signal_multiplexer.cpp
+apps/cloud_composer/src/toolbox_model.cpp
+apps/cloud_composer/src/transform_clouds.cpp
+apps/cloud_composer/src/work_queue.cpp
+apps/3d_rec_framework
+apps/in_hand_scanner
+apps/include
+apps/modeler
+apps/src
+benchmarks
+2d
+geometry
+ml
+octree
+simulation
+stereo
+tracking
+registration
+gpu/containers
+gpu/segmentation
# ChangeList
+## = 1.15.1 (26 August 2025) =
+
+### Notable changes
+
+**New features** *added to PCL*
+
+* **[search]** Add support for nanoflann (faster alternative to pcl::search::KdTree) [[#6250](https://github.com/PointCloudLibrary/pcl/pull/6250)]
+
+### Changes grouped by module
+
+#### CMake:
+
+* Fix get the root directory path of Boost [[#6259](https://github.com/PointCloudLibrary/pcl/pull/6259)]
+* Detect alignment when pcl_find_sse is not called & fix detection of Eigen [[#6261](https://github.com/PointCloudLibrary/pcl/pull/6261)]
+* Improve SSE/AVX detection on arm and when cross-compiling [[#6264](https://github.com/PointCloudLibrary/pcl/pull/6264)]
+* Fix CMake warning related to FLANN_ROOT [[#6266](https://github.com/PointCloudLibrary/pcl/pull/6266)]
+
+#### libpcl_common:
+
+* Make copyPoint work with point types having a field of the same name … [[#6300](https://github.com/PointCloudLibrary/pcl/pull/6300)]
+* Add potentially missing include cassert [[#6308](https://github.com/PointCloudLibrary/pcl/pull/6308)]
+
+#### libpcl_cuda:
+
+* Support CUDA 13 [[#6316](https://github.com/PointCloudLibrary/pcl/pull/6316)]
+
+#### libpcl_filters:
+
+* Make FarthestPointFilter respect user supplied indices [[#6286](https://github.com/PointCloudLibrary/pcl/pull/6286)]
+* Re-add instantiation of Convolution for MSVC [[#6310](https://github.com/PointCloudLibrary/pcl/pull/6310)]
+
+#### libpcl_gpu:
+
+* Fix CUDA 12.9 transform_reduce ambiguity [[#6299](https://github.com/PointCloudLibrary/pcl/pull/6299)]
+* Support CUDA 13 [[#6316](https://github.com/PointCloudLibrary/pcl/pull/6316)]
+
+#### libpcl_io:
+
+* Fix writing pcl::PointCloud to IFS file [[#6262](https://github.com/PointCloudLibrary/pcl/pull/6262)]
+* Increase accuracy of OctreePointCloudCompression [[#6273](https://github.com/PointCloudLibrary/pcl/pull/6273)]
+
+#### libpcl_ml:
+
+* Fix deprecated vsprintf warning in SVM implementation [[#6312](https://github.com/PointCloudLibrary/pcl/pull/6312)]
+
+#### libpcl_octree:
+
+* Increase accuracy of OctreePointCloudCompression [[#6273](https://github.com/PointCloudLibrary/pcl/pull/6273)]
+* Optimization for Octree radiusSearch [[#6313](https://github.com/PointCloudLibrary/pcl/pull/6313)]
+
+#### libpcl_outofcore:
+
+* Make the dependency of "outofcore" on "visualization" optional. [[#6254](https://github.com/PointCloudLibrary/pcl/pull/6254)]
+
+#### libpcl_registration:
+
+* add explicit instantiations to transformation estimation LM and one to ICP [[#6258](https://github.com/PointCloudLibrary/pcl/pull/6258)]
+* Make GICP use CorrespondenceEstimation [[#6278](https://github.com/PointCloudLibrary/pcl/pull/6278)]
+
+#### libpcl_sample_consensus:
+
+* SAC: add getInliers, getModel, getModelCoefficients to avoid copying data [[#6304](https://github.com/PointCloudLibrary/pcl/pull/6304)]
+
+#### libpcl_search:
+
+* **[new feature]** Add support for nanoflann (faster alternative to pcl::search::KdTree) [[#6250](https://github.com/PointCloudLibrary/pcl/pull/6250)]
+* Add option to manually set projection matrix in OrganizedNeighbor [[#6268](https://github.com/PointCloudLibrary/pcl/pull/6268)]
+
+#### libpcl_simulation:
+
+* Simulation: replace gluErrorString with switch-case [[#6253](https://github.com/PointCloudLibrary/pcl/pull/6253)]
+
+#### libpcl_surface:
+
+* Fix: Potential Vulnerability in Cloned zlib-Function [[#6245](https://github.com/PointCloudLibrary/pcl/pull/6245)]
+* Fix: Potential Vulnerability in Cloned zlib-Function [[#6246](https://github.com/PointCloudLibrary/pcl/pull/6246)]
+* Fix potential vulnerable cloned zlib-functions [[#6275](https://github.com/PointCloudLibrary/pcl/pull/6275)]
+* Fix potential vulnerable cloned zlib-functions [[#6274](https://github.com/PointCloudLibrary/pcl/pull/6274)]
+
+#### PCL Docs:
+
+* Modernize cmake config template [[#6235](https://github.com/PointCloudLibrary/pcl/pull/6235)]
+
+#### PCL Tutorials:
+
+* Update CMake commands in tutorials [[#6282](https://github.com/PointCloudLibrary/pcl/pull/6282)]
+
+#### CI:
+
+* Update/improve CI [[#6242](https://github.com/PointCloudLibrary/pcl/pull/6242)]
+* switch to VS 2022 on x64 Windows [[#6247](https://github.com/PointCloudLibrary/pcl/pull/6247)]
+* Add and use python for formatting. [[#6298](https://github.com/PointCloudLibrary/pcl/pull/6298)]
+
## = 1.15.0 (22 February 2025) =
### Notable changes
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type default to RelWithDebInfo, set to Release to improve performance" FORCE)
endif()
-project(PCL VERSION 1.15.0)
+project(PCL VERSION 1.15.1)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
if(MSVC AND ("${MSVC_VERSION}" LESS 1910))
set(CMAKE_COMPILER_IS_MINGW 1)
endif()
+# Ensure try_compile sets the include paths (e.g. for Eigen3)
+set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
+
# https://github.com/fish-shell/fish-shell/issues/5865
include(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_SOURCE_DIR}/cmake/custom_output.sh")
endif()
+# check for allocation functions that return aligned memory
+include("${PCL_SOURCE_DIR}/cmake/pcl_alignment.cmake")
+PCL_CHECK_FOR_ALIGNMENT()
+
# check for SSE flags
include("${PCL_SOURCE_DIR}/cmake/pcl_find_sse.cmake")
if(PCL_ENABLE_SSE AND "${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}")
if(CMAKE_COMPILER_IS_CLANG)
if("${CMAKE_C_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}")
- set(CMAKE_C_FLAGS "-Qunused-arguments")
+ string(APPEND CMAKE_C_FLAGS " -Wall -Wextra")
endif()
if("${CMAKE_CXX_FLAGS}" STREQUAL "")
- set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args
+ set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args
if(APPLE AND WITH_CUDA AND CUDA_FOUND)
string(APPEND CMAKE_CXX_FLAGS " -stdlib=libstdc++")
endif()
+ string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra")
endif()
set(CLANG_LIBRARIES "stdc++")
endif()
endif()
endif()
+find_package(nanoflann 1.4.2 QUIET)
+if(TARGET nanoflann::nanoflann)
+ set(PCL_HAS_NANOFLANN 1)
+ message(STATUS "Found nanoflann")
+else()
+ message(STATUS "nanoflann was not found, so some PCL classes will not be available.")
+endif()
+
# libusb
option(WITH_LIBUSB "Build USB RGBD-Camera drivers" TRUE)
if(WITH_LIBUSB)
if(ZLIB_FOUND)
set(HAVE_ZLIB ON)
endif()
+else()
+ message(WARNING "CMake will use a ZLIB version bundled with the PCL source code. However, that is an older version which may pose a risk and may be removed in a future PCL release. It is recommended to install an up-to-date version of ZLIB on your system and set WITH_SYSTEM_ZLIB=TRUE.")
endif()
option(WITH_SYSTEM_CJSON "Use system cJSON" TRUE)
endif()
unset(CMAKE_REQUIRED_LIBRARIES)
+### --[ Set variables for pcl_config.h
+if (BUILD_visualization)
+ set(PCL_VISUALIZATION_AVAILABLE TRUE)
+endif()
+
### ---[ Create the config.h file
set(pcl_config_h_in "${CMAKE_CURRENT_SOURCE_DIR}/pcl_config.h.in")
set(pcl_config_h "${CMAKE_CURRENT_BINARY_DIR}/include/pcl/pcl_config.h")
PCL_ADD_INCLUDES(common "" "${pcl_config_h}")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
+## ---[ PCL modules
collect_subproject_directory_names("${PCL_SOURCE_DIR}" "CMakeLists.txt" PCL_MODULES_NAMES PCL_MODULES_DIRS doc)
set(PCL_MODULES_NAMES_UNSORTED ${PCL_MODULES_NAMES})
topological_sort(PCL_MODULES_NAMES PCL_ _DEPENDS)
# ------------------------------------------------------------------------------------
# Helper to use PCL from outside project
#
-# target_link_libraries(my_fabulous_target PCL_XXX_LIBRARIES) where XXX is the
-# upper cased xxx from :
+# Search for PCL:
+# Request all PCL modules:
+# find_package(PCL CONFIG REQUIRED)
+# Or request only specific PCL modules:
+# find_package(PCL CONFIG REQUIRED COMPONENTS xxx yyy)
+#
+# Link to PCL:
+# Link to all found PCL modules:
+# target_link_libraries(my_fabulous_target ${PCL_LIBRARIES})
+# Or link only to specific modules:
+# target_link_libraries(my_fabulous_target pcl_xxx pcl_yyy)
+#
+# Where xxx and yyy are module names from the following list:
# @PCLCONFIG_AVAILABLE_COMPONENTS_LIST@
#
+# Some additional variables are set by PCLConfig.cmake, which are not needed when
+# using the (modern) linking approach described above:
# PCL_INCLUDE_DIRS is filled with PCL and available 3rdparty headers
# PCL_LIBRARY_DIRS is filled with PCL components libraries install directory and
# 3rdparty libraries paths
# www.pointclouds.org
#------------------------------------------------------------------------------------
+
# Set default policy behavior similar to minimum requirement version
cmake_policy(VERSION 3.16.3)
+if(POLICY CMP0144)
+ cmake_policy(SET CMP0144 NEW)
+endif()
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules")
### ---[ some useful macros
[![Release][release-image]][releases]
[![License][license-image]][license]
-[release-image]: https://img.shields.io/badge/release-1.15.0-green.svg?style=flat
+[release-image]: https://img.shields.io/badge/release-1.15.1-green.svg?style=flat
[releases]: https://github.com/PointCloudLibrary/pcl/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
[ci-ubuntu-22.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=Ubuntu&configuration=Ubuntu%2022.04%20Clang&label=Ubuntu%2022.04%20Clang
[ci-ubuntu-24.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2024.04%20GCC&label=Ubuntu%2024.04%20GCC
[ci-windows-x86]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x86&label=Windows%20VS2019%20x86
-[ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2019%20x64
+[ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2022%20x64
[ci-macos-13]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Ventura%2013&label=macOS%20Ventura%2013
[ci-macos-14]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Sonoma%2014&label=macOS%20Sonoma%2014
[ci-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/Documentation?branchName=master
class QItemSelectionModel;
-namespace pcl
-{
- namespace cloud_composer
- {
- /** \brief View class for displaying project composition
- * \author Jeremie Papon
- * \ingroup cloud_composer
- */
- class ProjectModel;
- class CloudBrowser : public QTreeView
- {
- Q_OBJECT
- public:
- CloudBrowser (QWidget* parent = nullptr);
-
- void
- setModel (QAbstractItemModel* new_model) override;
-
- private:
- ProjectModel* current_project_model_;
-
- };
-
- class BackgroundDelegate : public QStyledItemDelegate
- {
- public:
- explicit
- BackgroundDelegate (QObject *parent = nullptr)
- : QStyledItemDelegate(parent) {}
-
- void
- paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
-
- };
-
- }
-}
+namespace pcl {
+namespace cloud_composer {
+/** \brief View class for displaying project composition
+ * \author Jeremie Papon
+ * \ingroup cloud_composer
+ */
+class ProjectModel;
+class CloudBrowser : public QTreeView {
+ Q_OBJECT
+public:
+ CloudBrowser(QWidget* parent = nullptr);
+
+ void
+ setModel(QAbstractItemModel* new_model) override;
+
+private:
+ ProjectModel* current_project_model_;
+};
+
+class BackgroundDelegate : public QStyledItemDelegate {
+public:
+ explicit BackgroundDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent)
+ {}
+
+ void
+ paint(QPainter* painter,
+ const QStyleOptionViewItem& option,
+ const QModelIndex& index) const override;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#pragma once
-//PCL
+// PCL
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
class QTreeView;
-namespace pcl
-{
- namespace cloud_composer
- {
- class ProjectModel;
- class CloudViewer;
- class CloudCommand;
- class ToolFactory;
- class ToolBoxModel;
- class SignalMultiplexer;
-
- /** \brief MainWindow of cloud_composer application
- * \author Jeremie Papon
- * \ingroup cloud_composer
- * The following member objects are defined in the ui file and can be manipulated:
- * * cloud_viewer_ is the view which contains the PCLVisualizer & QVTKWidget
- * * cloud_browser_ is the tree view in the left dock
- * * item_inspector_ is the details view in the left dock
- * * tool_box_view_ is the tool box in right dock
- * * tool_parameter_view_ shows adjustable parameters for currently selected tool
- * * undo_view_ is the undo stack view in the right dock
- */
- class ComposerMainWindow : public QMainWindow, private Ui::ComposerMainWindow
- {
- Q_OBJECT
- public:
- explicit ComposerMainWindow (QWidget *parent = nullptr);
- ~ComposerMainWindow ();
-
- Q_SIGNALS:
- /** \brief Signal emitted when the active project is switched - ie a different project tab is selected */
- void
- activeProjectChanged (ProjectModel* new_model, ProjectModel* previous_model);
-
- /** \brief This signal tells the current project to insert a cloud using a file dialog box */
- void
- insertNewCloudFromFile ();
-
- /** \brief This signal tells the current project to insert a cloud from and RGB and Depth image using a file dialog box */
- void
- insertNewCloudFromRGBandDepth ();
-
- /** \brief This signal tells the current project to save currently selected cloud to file */
- void
- saveSelectedCloudToFile ();
-
- public Q_SLOTS:
- //Slots for File Menu Actions
- void
- on_action_new_project__triggered (/*QString name = "unsaved project"*/);
- void
- on_action_open_cloud_as_new_project__triggered ();
- void
- on_action_open_project__triggered ();
- void
- on_action_save_project__triggered ();
- void
- on_action_save_project_as__triggered ();
- void
- on_action_save_selected_cloud__triggered ();
- void
- on_action_exit__triggered ();
-
- //Slots for Edit Menu Actions
- void
- on_action_insert_from_file__triggered ();
- void
- on_action_insert_from_openNi_source__triggered ();
- void
- on_action_insert_from_rgb_depth__triggered ();
-
-
-
- void
- setCurrentModel (ProjectModel* model);
-
- void
- setMouseStyleAction (interactor_styles::INTERACTOR_STYLES selected_style);
-
- void
- enqueueToolAction (AbstractTool* tool);
-
- private:
- void
- connectFileActions ();
- void
- connectEditActions ();
-
- void
- connectViewActions ();
-
- void
- initializeCloudBrowser ();
- void
- initializeCloudViewer ();
- void
- initializeItemInspector ();
-
- void
- initializeToolBox ();
- void
- initializePlugins ();
-
-
- /** \brief Pointer to the model which is currently being viewed */
- ProjectModel* current_model_;
- QItemSelectionModel* current_selection_model_;
-
- QMap <QString, ProjectModel*> name_model_map_;
-
- QUndoGroup *undo_group_;
-
- QItemSelectionModel* tool_selection_model_;
- ToolBoxModel* tool_box_model_;
-
- SignalMultiplexer* multiplexer_;
-
- QActionGroup* mouse_style_group_;
- };
-
- }
-}
+namespace pcl {
+namespace cloud_composer {
+class ProjectModel;
+class CloudViewer;
+class CloudCommand;
+class ToolFactory;
+class ToolBoxModel;
+class SignalMultiplexer;
+
+/** \brief MainWindow of cloud_composer application
+ * \author Jeremie Papon
+ * \ingroup cloud_composer
+ * The following member objects are defined in the ui file and can be manipulated:
+ * * cloud_viewer_ is the view which contains the PCLVisualizer & QVTKWidget
+ * * cloud_browser_ is the tree view in the left dock
+ * * item_inspector_ is the details view in the left dock
+ * * tool_box_view_ is the tool box in right dock
+ * * tool_parameter_view_ shows adjustable parameters for currently selected tool
+ * * undo_view_ is the undo stack view in the right dock
+ */
+class ComposerMainWindow : public QMainWindow, private Ui::ComposerMainWindow {
+ Q_OBJECT
+public:
+ explicit ComposerMainWindow(QWidget* parent = nullptr);
+ ~ComposerMainWindow();
+
+Q_SIGNALS:
+ /** \brief Signal emitted when the active project is switched - ie a different project
+ * tab is selected */
+ void
+ activeProjectChanged(ProjectModel* new_model, ProjectModel* previous_model);
+
+ /** \brief This signal tells the current project to insert a cloud using a file dialog
+ * box */
+ void
+ insertNewCloudFromFile();
+
+ /** \brief This signal tells the current project to insert a cloud from and RGB and
+ * Depth image using a file dialog box */
+ void
+ insertNewCloudFromRGBandDepth();
+
+ /** \brief This signal tells the current project to save currently selected cloud to
+ * file */
+ void
+ saveSelectedCloudToFile();
+
+public Q_SLOTS:
+ // Slots for File Menu Actions
+ void on_action_new_project__triggered(/*QString name = "unsaved project"*/);
+ void
+ on_action_open_cloud_as_new_project__triggered();
+ void
+ on_action_open_project__triggered();
+ void
+ on_action_save_project__triggered();
+ void
+ on_action_save_project_as__triggered();
+ void
+ on_action_save_selected_cloud__triggered();
+ void
+ on_action_exit__triggered();
+
+ // Slots for Edit Menu Actions
+ void
+ on_action_insert_from_file__triggered();
+ void
+ on_action_insert_from_openNi_source__triggered();
+ void
+ on_action_insert_from_rgb_depth__triggered();
+
+ void
+ setCurrentModel(ProjectModel* model);
+
+ void
+ setMouseStyleAction(interactor_styles::INTERACTOR_STYLES selected_style);
+
+ void
+ enqueueToolAction(AbstractTool* tool);
+
+private:
+ void
+ connectFileActions();
+ void
+ connectEditActions();
+
+ void
+ connectViewActions();
+
+ void
+ initializeCloudBrowser();
+ void
+ initializeCloudViewer();
+ void
+ initializeItemInspector();
+
+ void
+ initializeToolBox();
+ void
+ initializePlugins();
+
+ /** \brief Pointer to the model which is currently being viewed */
+ ProjectModel* current_model_;
+ QItemSelectionModel* current_selection_model_;
+
+ QMap<QString, ProjectModel*> name_model_map_;
+
+ QUndoGroup* undo_group_;
+
+ QItemSelectionModel* tool_selection_model_;
+ ToolBoxModel* tool_box_model_;
+
+ SignalMultiplexer* multiplexer_;
+
+ QActionGroup* mouse_style_group_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#pragma once
-#include <QWidget>
-
-#include <vtkEventQtSlotConnect.h>
-
+#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/qvtk_compatibility.h>
-#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
+#include <QWidget>
-#include <vtkSmartPointer.h>
-#include <vtkOrientationMarkerWidget.h>
#include <vtkAxesActor.h>
+#include <vtkEventQtSlotConnect.h>
+#include <vtkOrientationMarkerWidget.h>
+#include <vtkSmartPointer.h>
#include <vtkVersion.h>
class QItemSelection;
class QStandardItem;
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class ProjectModel;
+/** \brief View class for displaying ProjectModel data using PCLVisualizer
+ * \author Jeremie Papon
+ * \ingroup cloud_composer
+ */
+class CloudView : public QWidget {
+ Q_OBJECT
+
+public:
+ CloudView(QWidget* parent = nullptr);
+ CloudView(const CloudView& to_copy);
+ CloudView(ProjectModel* model, QWidget* parent = nullptr);
+
+ void
+ setModel(ProjectModel* new_model);
+
+ ProjectModel*
+ getModel() const
+ {
+ return model_;
+ }
+
+ PCLQVTKWidget*
+ getQVTK() const
+ {
+ return qvtk_;
+ }
+
+ pcl::visualization::PCLVisualizer::Ptr
+ getPCLVisualizer() const
{
- class ProjectModel;
- /** \brief View class for displaying ProjectModel data using PCLVisualizer
- * \author Jeremie Papon
- * \ingroup cloud_composer
- */
- class CloudView : public QWidget
- {
- Q_OBJECT
-
- public:
- CloudView (QWidget* parent = nullptr);
- CloudView (const CloudView& to_copy);
- CloudView (ProjectModel* model, QWidget* parent = nullptr);
-
- void
- setModel (ProjectModel* new_model);
-
- ProjectModel*
- getModel () const { return model_; }
-
- PCLQVTKWidget*
- getQVTK() const { return qvtk_; }
-
- pcl::visualization::PCLVisualizer::Ptr
- getPCLVisualizer () const { return vis_; }
-
- void
- setAxisVisibility (bool visible);
-
- void
- setInteractorStyle (interactor_styles::INTERACTOR_STYLES style);
- public Q_SLOTS:
- void
- refresh ();
-
- /** \brief Slot called when the item selected in cloud browser changes */
- void
- selectedItemChanged (const QItemSelection & selected, const QItemSelection & deselected);
-
- /** \brief Slot called when the data in model changes */
- void
- dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight );
-
- protected Q_SLOTS:
- /** \brief Slot called when an item in the model changes
- * \param topLeft
- * \param bottomRight
- */
- void
- itemChanged (QStandardItem* item);
-
- /** \brief Slot called when rows inserted to model
- * \param start Start of new rows (inclusive)
- * \param end End of new rows (inclusive)
- */
- void
- rowsInserted (const QModelIndex& parent, int start, int end);
-
- void
- rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
-
- void
- selectionCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data);
-
- void
- manipulationCompleted (vtkObject* caller, unsigned long event_id, void* client_data, void* call_data);
-
- protected:
- void
- paintEvent (QPaintEvent* event) override;
- void
- resizeEvent (QResizeEvent* event) override;
- // void scrollContentsBy (int dx, int dy);
-
-
-
- private:
- void
- connectSignalsAndSlots ();
-
- /** \brief Internal function for setting up the style_switch_ */
- void
- initializeInteractorSwitch ();
-
- void
- addOrientationMarkerWidgetAxes ();
- void
- removeOrientationMarkerWidgetAxes ();
-
- pcl::visualization::PCLVisualizer::Ptr vis_;
- ProjectModel* model_;
-
- PCLQVTKWidget* qvtk_;
-
- vtkSmartPointer<InteractorStyleSwitch> style_switch_;
-
- vtkSmartPointer<vtkOrientationMarkerWidget> axes_widget_;
- vtkSmartPointer<vtkAxesActor> axes_;
-
- /** \brief Manages VTK events by connecting them to QT slots */
- vtkSmartPointer<vtkEventQtSlotConnect> connections_;
- };
+ return vis_;
}
-}
-Q_DECLARE_METATYPE (pcl::cloud_composer::CloudView);
+ void
+ setAxisVisibility(bool visible);
+
+ void
+ setInteractorStyle(interactor_styles::INTERACTOR_STYLES style);
+public Q_SLOTS:
+ void
+ refresh();
+
+ /** \brief Slot called when the item selected in cloud browser changes */
+ void
+ selectedItemChanged(const QItemSelection& selected, const QItemSelection& deselected);
+
+ /** \brief Slot called when the data in model changes */
+ void
+ dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
+
+protected Q_SLOTS:
+ /** \brief Slot called when an item in the model changes
+ * \param topLeft
+ * \param bottomRight
+ */
+ void
+ itemChanged(QStandardItem* item);
+
+ /** \brief Slot called when rows inserted to model
+ * \param start Start of new rows (inclusive)
+ * \param end End of new rows (inclusive)
+ */
+ void
+ rowsInserted(const QModelIndex& parent, int start, int end);
+
+ void
+ rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end);
+
+ void
+ selectionCompleted(vtkObject* caller,
+ unsigned long event_id,
+ void* client_data,
+ void* call_data);
+
+ void
+ manipulationCompleted(vtkObject* caller,
+ unsigned long event_id,
+ void* client_data,
+ void* call_data);
+
+protected:
+ void
+ paintEvent(QPaintEvent* event) override;
+ void
+ resizeEvent(QResizeEvent* event) override;
+ // void scrollContentsBy (int dx, int dy);
+
+private:
+ void
+ connectSignalsAndSlots();
+
+ /** \brief Internal function for setting up the style_switch_ */
+ void
+ initializeInteractorSwitch();
+
+ void
+ addOrientationMarkerWidgetAxes();
+ void
+ removeOrientationMarkerWidgetAxes();
+
+ pcl::visualization::PCLVisualizer::Ptr vis_;
+ ProjectModel* model_;
+
+ PCLQVTKWidget* qvtk_;
+
+ vtkSmartPointer<InteractorStyleSwitch> style_switch_;
+
+ vtkSmartPointer<vtkOrientationMarkerWidget> axes_widget_;
+ vtkSmartPointer<vtkAxesActor> axes_;
+
+ /** \brief Manages VTK events by connecting them to QT slots */
+ vtkSmartPointer<vtkEventQtSlotConnect> connections_;
+};
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(pcl::cloud_composer::CloudView);
#pragma once
+#include <pcl/apps/cloud_composer/cloud_view.h>
+#include <pcl/apps/cloud_composer/project_model.h>
+#include <pcl/visualization/pcl_visualizer.h>
+
#include <QTabWidget>
-#include <pcl/visualization/pcl_visualizer.h>
-#include <pcl/apps/cloud_composer/project_model.h>
-#include <pcl/apps/cloud_composer/cloud_view.h>
+namespace pcl {
+namespace cloud_composer {
+
+/** \brief Tabbed widget for containing CloudView widgets
+ * \author Jeremie Papon
+ * \ingroup cloud_composer
+ */
+class CloudViewer : public QTabWidget {
+ Q_OBJECT
+
+public:
+ CloudViewer(QWidget* parent = nullptr);
+ ProjectModel*
+ getModel() const;
+
+public Q_SLOTS:
+ void
+ addModel(ProjectModel* new_model);
-namespace pcl
-{
- namespace cloud_composer
- {
-
- /** \brief Tabbed widget for containing CloudView widgets
- * \author Jeremie Papon
- * \ingroup cloud_composer
- */
- class CloudViewer : public QTabWidget
- {
- Q_OBJECT
+ void
+ modelChanged(int index);
- public:
-
- CloudViewer (QWidget* parent = nullptr);
- ProjectModel* getModel () const;
+ void
+ addNewProject(ProjectModel* new_model);
- public Q_SLOTS:
- void
- addModel (ProjectModel* new_model);
-
- void
- modelChanged (int index);
-
- void
- addNewProject (ProjectModel* new_model);
-
- Q_SIGNALS:
- void
- newModelSelected (ProjectModel *new_model);
+Q_SIGNALS:
+ void
+ newModelSelected(ProjectModel* new_model);
- private:
-
- pcl::visualization::PCLVisualizer::Ptr vis_;
- QMap <ProjectModel*, CloudView*> model_view_map_;
- };
- }
-}
+private:
+ pcl::visualization::PCLVisualizer::Ptr vis_;
+ QMap<ProjectModel*, CloudView*> model_view_map_;
+};
+} // namespace cloud_composer
+} // namespace pcl
#include <QUndoCommand>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class AbstractTool;
+class ProjectModel;
+struct OutputPair {
+ QList<const CloudComposerItem*> input_items_;
+ QList<CloudComposerItem*> output_items_;
+};
+
+class CloudCommand : public QUndoCommand {
+public:
+ CloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ ~CloudCommand();
+
+ virtual bool
+ runCommand(AbstractTool* tool) = 0;
+
+ void
+ undo() override = 0;
+
+ void
+ redo() override = 0;
+
+ // QList <CloudComposerItem*>
+ // executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data);
+
+ void
+ setProjectModel(ProjectModel* model);
+
+ inline void
+ setInputData(ConstItemList input_data)
+ {
+ original_data_ = std::move(input_data);
+ }
+
+protected:
+ /** \brief Removes the original item(s) from the model and replaces with the
+ * replacement(s) Replacements are only inserted once, original items must have same
+ * parent This stores the removed items in removed_items_
+ */
+ bool
+ replaceOriginalWithNew(const QList<const CloudComposerItem*>& originals,
+ const QList<CloudComposerItem*>& new_items);
+
+ /** \brief This removes new_items from the model and restores originals */
+ bool
+ restoreOriginalRemoveNew(const QList<const CloudComposerItem*>& originals,
+ const QList<CloudComposerItem*>& new_items);
+
+ ConstItemList original_data_;
+
+ QMap<QStandardItem*, QStandardItem*> removed_to_parent_map_;
+ QList<OutputPair> output_data_;
+ ProjectModel* project_model_;
+
+ /** \brief This determines if we delete original items or not on destruction
+ * If the command is being deleted because stack is at limit, then we want
+ * to only delete the originals, since the command is staying for good (new items
+ * shouldn't be deleted) On the other hand, if we destruct after an undo, then we want
+ * to delete the new items (but not the originals)
+ */
+ bool last_was_undo_;
+
+ /** \brief This is used to check if a templated version of a tool can be used
+ * For this to return true, all items must be clouds, and must have the same template
+ * type
+ */
+ bool
+ canUseTemplates(ConstItemList& input_data);
+
+ bool can_use_templates_;
+ int template_type_;
+};
+
+class ModifyItemCommand : public CloudCommand {
+public:
+ ModifyItemCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ bool
+ runCommand(AbstractTool* tool) override;
+
+ void
+ undo() override;
+
+ void
+ redo() override;
+
+private:
+};
+
+class NewItemCloudCommand : public CloudCommand {
+public:
+ NewItemCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ bool
+ runCommand(AbstractTool* tool) override;
+
+ void
+ undo() override;
+
+ void
+ redo() override;
+};
+
+class SplitCloudCommand : public CloudCommand {
+public:
+ SplitCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ bool
+ runCommand(AbstractTool* tool) override;
+
+ void
+ undo() override;
+
+ void
+ redo() override;
+
+private:
+};
+
+class DeleteItemCommand : public CloudCommand {
+public:
+ DeleteItemCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ bool
+ runCommand(AbstractTool* tool) override;
+
+ void
+ undo() override;
+
+ void
+ redo() override;
+
+private:
+};
+
+class MergeCloudCommand : public CloudCommand {
+public:
+ /** \brief Construct for a merge command
+ * \param[in] input_data Input list of CloudItem s from the project model which will
+ * be merged \param[in] temporary_clouds Input list of CloudItems which
+ */
+ MergeCloudCommand(ConstItemList input_data, QUndoCommand* parent = nullptr);
+
+ bool
+ runCommand(AbstractTool* tool) override;
+
+ void
+ undo() override;
+
+ void
+ redo() override;
+
+ inline void
+ setSelectedIndicesMap(
+ const QMap<CloudItem*, pcl::PointIndices::Ptr>& selected_item_index_map)
{
- class AbstractTool;
- class ProjectModel;
- struct OutputPair
- {
- QList <const CloudComposerItem*> input_items_;
- QList <CloudComposerItem*> output_items_;
- };
-
-
-
- class CloudCommand : public QUndoCommand
- {
- public:
- CloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
-
- ~CloudCommand ();
-
- virtual bool
- runCommand (AbstractTool* tool) = 0;
-
- void
- undo () override = 0;
-
- void
- redo () override = 0;
-
- //QList <CloudComposerItem*>
- // executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data);
-
- void
- setProjectModel (ProjectModel* model);
-
- inline void
- setInputData (ConstItemList input_data)
- {
- original_data_ = std::move(input_data);
- }
- protected:
- /** \brief Removes the original item(s) from the model and replaces with the replacement(s)
- * Replacements are only inserted once, original items must have same parent
- * This stores the removed items in removed_items_
- */
- bool
- replaceOriginalWithNew (const QList <const CloudComposerItem*>& originals, const QList <CloudComposerItem*>& new_items);
-
- /** \brief This removes new_items from the model and restores originals */
- bool
- restoreOriginalRemoveNew (const QList <const CloudComposerItem*>& originals, const QList <CloudComposerItem*>& new_items);
-
- ConstItemList original_data_;
-
- QMap <QStandardItem*, QStandardItem*> removed_to_parent_map_;
- QList <OutputPair> output_data_;
- ProjectModel* project_model_;
-
- /** \brief This determines if we delete original items or not on destruction
- * If the command is being deleted because stack is at limit, then we want
- * to only delete the originals, since the command is staying for good (new items shouldn't be deleted)
- * On the other hand, if we destruct after an undo, then we want to delete the new items (but not the originals)
- */
- bool last_was_undo_;
-
- /** \brief This is used to check if a templated version of a tool can be used
- * For this to return true, all items must be clouds, and must have the same template type
- */
- bool
- canUseTemplates (ConstItemList &input_data);
-
- bool can_use_templates_;
- int template_type_;
- };
-
- class ModifyItemCommand : public CloudCommand
- {
- public:
- ModifyItemCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
- bool
- runCommand (AbstractTool* tool) override;
-
- void
- undo () override;
-
- void
- redo () override;
- private:
-
-
-
- };
-
- class NewItemCloudCommand : public CloudCommand
- {
- public:
- NewItemCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
- bool
- runCommand (AbstractTool* tool) override;
-
- void
- undo () override;
-
- void
- redo () override;
-
- };
-
-
- class SplitCloudCommand : public CloudCommand
- {
- public:
- SplitCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
- bool
- runCommand (AbstractTool* tool) override;
-
- void
- undo () override;
-
- void
- redo () override;
- private:
-
- };
-
- class DeleteItemCommand : public CloudCommand
- {
- public:
- DeleteItemCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
- bool
- runCommand (AbstractTool* tool) override;
-
- void
- undo () override;
-
- void
- redo () override;
- private:
- };
-
- class MergeCloudCommand : public CloudCommand
- {
- public:
- /** \brief Construct for a merge command
- * \param[in] input_data Input list of CloudItem s from the project model which will be merged
- * \param[in] temporary_clouds Input list of CloudItems which
- */
- MergeCloudCommand (ConstItemList input_data, QUndoCommand* parent = nullptr);
-
- bool
- runCommand (AbstractTool* tool) override;
-
- void
- undo () override;
-
- void
- redo () override;
-
- inline void
- setSelectedIndicesMap( const QMap <CloudItem*, pcl::PointIndices::Ptr >& selected_item_index_map)
- {
- selected_item_index_map_ = selected_item_index_map;
- }
-
- private:
- QMap <CloudItem*, pcl::PointIndices::Ptr > selected_item_index_map_;
- };
+ selected_item_index_map_ = selected_item_index_map;
}
-}
-Q_DECLARE_METATYPE (ConstItemList);
+private:
+ QMap<CloudItem*, pcl::PointIndices::Ptr> selected_item_index_map_;
+};
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(ConstItemList);
- /*
+/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
#define IMPL_CLOUD_ITEM_H_
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-#include <pcl/memory.h> // for pcl::make_shared
-#include <pcl/point_cloud.h>
#include <pcl/impl/instantiate.hpp>
+#include <pcl/memory.h> // for pcl::make_shared
+#include <pcl/point_cloud.h>
-template <typename PointT> void
-pcl::cloud_composer::CloudItem::printNumPoints () const
+template <typename PointT>
+void
+pcl::cloud_composer::CloudItem::printNumPoints() const
{
- QVariant variant = this->data (ItemDataRole::CLOUD_TEMPLATED);
+ QVariant variant = this->data(ItemDataRole::CLOUD_TEMPLATED);
typename PointCloud<PointT>::Ptr cloud;
- if ( variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
+ if (variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ cloud = variant.value<typename PointCloud<PointT>::Ptr>();
}
- else
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item!";
+ else {
+ qWarning()
+ << "Attempted to cast to template type which does not exist in this item!";
return;
}
- qDebug () << "CLOUD HAS WIDTH = "<< cloud->width;
-
+ qDebug() << "CLOUD HAS WIDTH = " << cloud->width;
}
-
-
-template <typename PointT> pcl::cloud_composer::CloudItem*
-pcl::cloud_composer::CloudItem::createCloudItemFromTemplate (const QString& name, typename PointCloud<PointT>::Ptr cloud_ptr)
+template <typename PointT>
+pcl::cloud_composer::CloudItem*
+pcl::cloud_composer::CloudItem::createCloudItemFromTemplate(
+ const QString& name, typename PointCloud<PointT>::Ptr cloud_ptr)
{
- pcl::PCLPointCloud2::Ptr cloud_blob = pcl::make_shared <pcl::PCLPointCloud2> ();
- toPCLPointCloud2 (*cloud_ptr, *cloud_blob);
- CloudItem* cloud_item = new CloudItem ( name, cloud_blob, Eigen::Vector4f (), Eigen::Quaternionf (), false);
- cloud_item->setData (QVariant::fromValue(cloud_ptr), ItemDataRole::CLOUD_TEMPLATED);
- cloud_item->setPointType<PointT> ();
+ pcl::PCLPointCloud2::Ptr cloud_blob = pcl::make_shared<pcl::PCLPointCloud2>();
+ toPCLPointCloud2(*cloud_ptr, *cloud_blob);
+ CloudItem* cloud_item =
+ new CloudItem(name, cloud_blob, Eigen::Vector4f(), Eigen::Quaternionf(), false);
+ cloud_item->setData(QVariant::fromValue(cloud_ptr), ItemDataRole::CLOUD_TEMPLATED);
+ cloud_item->setPointType<PointT>();
return cloud_item;
}
+#define PCL_INSTANTIATE_createCloudItemFromTemplate(T) \
+ template pcl::cloud_composer::CloudItem* \
+ pcl::cloud_composer::CloudItem::createCloudItemFromTemplate<T>( \
+ const QString, typename PointCloud<PointT>::Ptr);
-#define PCL_INSTANTIATE_createCloudItemFromTemplate(T) template pcl::cloud_composer::CloudItem* pcl::cloud_composer::CloudItem::createCloudItemFromTemplate<T>(const QString, typename PointCloud<PointT>::Ptr);
-
-#define PCL_INSTANTIATE_printNumPoints(T) template void pcl::cloud_composer::CloudItem::getNumPoints<T>();
+#define PCL_INSTANTIATE_printNumPoints(T) \
+ template void pcl::cloud_composer::CloudItem::getNumPoints<T>();
#endif
- /*
+/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
#ifndef IMPL_MERGE_SELECTION_H_
#define IMPL_MERGE_SELECTION_H_
+#include <pcl/apps/cloud_composer/impl/cloud_item.hpp>
#include <pcl/apps/cloud_composer/merge_selection.h>
+#include <pcl/filters/extract_indices.h>
#include <pcl/point_cloud.h>
-#include <pcl/apps/cloud_composer/impl/cloud_item.hpp>
-template <typename PointT> QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::MergeSelection::performTemplatedAction (const QList <const CloudComposerItem*>& input_data)
+template <typename PointT>
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::MergeSelection::performTemplatedAction(
+ const QList<const CloudComposerItem*>& input_data)
{
- QList <CloudComposerItem*> output;
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- if ( ! variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)";
+ QList<CloudComposerItem*> output;
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ if (!variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ qWarning() << "Attempted to cast to template type which does not exist in this "
+ "item! (input list)";
return output;
}
}
- foreach (const CloudItem* input_item, selected_item_index_map_.keys ())
- {
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- if ( ! variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item! (selected list)";
+ foreach (const CloudItem* input_item, selected_item_index_map_.keys()) {
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ if (!variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ qWarning() << "Attempted to cast to template type which does not exist in this "
+ "item! (selected list)";
return output;
}
- }
+ }
pcl::ExtractIndices<PointT> filter;
- typename PointCloud<PointT>::Ptr merged_cloud (new PointCloud<PointT>);
+ typename PointCloud<PointT>::Ptr merged_cloud(new PointCloud<PointT>);
+
+ foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys()) {
+ input_cloud_item->printNumPoints<PointT>();
+ // If this cloud hasn't been completely selected
+ if (!input_data.contains(input_cloud_item)) {
+ typename PointCloud<PointT>::Ptr input_cloud =
+ input_cloud_item->data(ItemDataRole::CLOUD_TEMPLATED)
+ .value<typename PointCloud<PointT>::Ptr>();
+ qDebug() << "Extracting "
+ << selected_item_index_map_.value(input_cloud_item)->indices.size()
+ << " points out of " << input_cloud->width;
+ filter.setInputCloud(input_cloud);
+ filter.setIndices(selected_item_index_map_.value(input_cloud_item));
+ typename PointCloud<PointT>::Ptr original_minus_indices(new PointCloud<PointT>);
+ filter.setNegative(true);
+ filter.filter(*original_minus_indices);
+ filter.setNegative(false);
+ typename PointCloud<PointT>::Ptr selected_points(new PointCloud<PointT>);
+ filter.filter(*selected_points);
+
+ qDebug() << "Original minus indices is " << original_minus_indices->width;
- foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys ())
- {
- input_cloud_item->printNumPoints <PointT> ();
- //If this cloud hasn't been completely selected
- if (!input_data.contains (input_cloud_item))
- {
- typename PointCloud<PointT>::Ptr input_cloud = input_cloud_item->data (ItemDataRole::CLOUD_TEMPLATED).value <typename PointCloud<PointT>::Ptr> ();
- qDebug () << "Extracting "<<selected_item_index_map_.value(input_cloud_item)->indices.size() << " points out of "<<input_cloud->width;
- filter.setInputCloud (input_cloud);
- filter.setIndices (selected_item_index_map_.value (input_cloud_item));
- typename PointCloud<PointT>::Ptr original_minus_indices (new PointCloud<PointT>);
- filter.setNegative (true);
- filter.filter (*original_minus_indices);
- filter.setNegative (false);
- typename PointCloud<PointT>::Ptr selected_points (new PointCloud<PointT>);
- filter.filter (*selected_points);
-
- qDebug () << "Original minus indices is "<<original_minus_indices->width;
-
- CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(input_cloud_item->text (),original_minus_indices);
-
- output.append (new_cloud_item);
+ CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(
+ input_cloud_item->text(), original_minus_indices);
+
+ output.append(new_cloud_item);
*merged_cloud += *selected_points;
}
- //Append the input item to the original list
- //input_data.append (input_cloud_item);
+ // Append the input item to the original list
+ // input_data.append (input_cloud_item);
}
- //Just concatenate for all fully selected clouds
- foreach (const CloudComposerItem* input_item, input_data)
- {
- typename PointCloud<PointT>::Ptr input_cloud = input_item->data (ItemDataRole::CLOUD_TEMPLATED).value <typename PointCloud<PointT>::Ptr> ();
+ // Just concatenate for all fully selected clouds
+ foreach (const CloudComposerItem* input_item, input_data) {
+ typename PointCloud<PointT>::Ptr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_TEMPLATED)
+ .value<typename PointCloud<PointT>::Ptr>();
*merged_cloud += *input_cloud;
}
- CloudItem* cloud_item = CloudItem::createCloudItemFromTemplate<PointT>("Cloud from Selection",merged_cloud);
-
- output.append (cloud_item);
-
- return output;
-
-}
+ CloudItem* cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(
+ "Cloud from Selection", merged_cloud);
+ output.append(cloud_item);
-#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::MergeSelection::performTemplatedAction<T> (QList <const CloudComposerItem*>);
-
+ return output;
+}
+#define PCL_INSTANTIATE_performTemplatedAction(T) \
+ template void pcl::cloud_composer::MergeSelection::performTemplatedAction<T>( \
+ QList<const CloudComposerItem*>);
-#endif //IMPL_MERGE_SELECTION_H_
+#endif // IMPL_MERGE_SELECTION_H_
- /*
+/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
#ifndef IMPL_TRANSFORM_CLOUDS_HPP_
#define IMPL_TRANSFORM_CLOUDS_HPP_
-#include <pcl/apps/cloud_composer/transform_clouds.h>
#include <pcl/apps/cloud_composer/impl/cloud_item.hpp>
-#include <pcl/point_cloud.h>
+#include <pcl/apps/cloud_composer/transform_clouds.h>
#include <pcl/common/transforms.h>
+#include <pcl/point_cloud.h>
-template <typename PointT> QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::TransformClouds::performTemplatedAction (const QList <const CloudComposerItem*>& input_data)
+template <typename PointT>
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::TransformClouds::performTemplatedAction(
+ const QList<const CloudComposerItem*>& input_data)
{
- QList <CloudComposerItem*> output;
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- if ( ! variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)";
+ QList<CloudComposerItem*> output;
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ if (!variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ qWarning() << "Attempted to cast to template type which does not exist in this "
+ "item! (input list)";
return output;
}
- if (!transform_map_.contains ("AllSelectedClouds") && !transform_map_.contains (input_item->getId ()))
- {
- qCritical () << "No transform found for id "<<input_item->getId ()<<" in TransformClouds::performTemplatedAction";
+ if (!transform_map_.contains("AllSelectedClouds") &&
+ !transform_map_.contains(input_item->getId())) {
+ qCritical() << "No transform found for id " << input_item->getId()
+ << " in TransformClouds::performTemplatedAction";
return output;
}
}
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- qDebug () << "Transforming cloud "<<input_item->getId ();
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- typename PointCloud <PointT>::Ptr input_cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
-
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ qDebug() << "Transforming cloud " << input_item->getId();
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ typename PointCloud<PointT>::Ptr input_cloud =
+ variant.value<typename PointCloud<PointT>::Ptr>();
+
Eigen::Matrix4f transform;
- if (transform_map_.contains ("AllSelectedClouds"))
- pcl::visualization::PCLVisualizer::convertToEigenMatrix (transform_map_.value ("AllSelectedClouds"), transform);
+ if (transform_map_.contains("AllSelectedClouds"))
+ pcl::visualization::PCLVisualizer::convertToEigenMatrix(
+ transform_map_.value("AllSelectedClouds"), transform);
else
- pcl::visualization::PCLVisualizer::convertToEigenMatrix (transform_map_.value (input_item->getId ()), transform);
-
- typename PointCloud<PointT>::Ptr transformed_cloud (new PointCloud<PointT>);
-
- transformPointCloud<PointT> (*input_cloud, *transformed_cloud, transform);
- CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(input_item->text (),transformed_cloud);
-
- output.append (new_cloud_item);
- }
+ pcl::visualization::PCLVisualizer::convertToEigenMatrix(
+ transform_map_.value(input_item->getId()), transform);
+
+ typename PointCloud<PointT>::Ptr transformed_cloud(new PointCloud<PointT>);
-
+ transformPointCloud<PointT>(*input_cloud, *transformed_cloud, transform);
+ CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(
+ input_item->text(), transformed_cloud);
+ output.append(new_cloud_item);
+ }
return output;
-
}
+#define PCL_INSTANTIATE_performTemplatedAction(T) \
+ template void pcl::cloud_composer::TransformClouds::performTemplatedAction<T>( \
+ QList<const CloudComposerItem*>);
-#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::TransformClouds::performTemplatedAction<T> (QList <const CloudComposerItem*>);
-
-
-
-#endif //IMPL_TRANSFORM_CLOUDS_HPP_
+#endif // IMPL_TRANSFORM_CLOUDS_HPP_
#pragma once
-#include <QTabWidget>
-
#include <pcl/apps/cloud_composer/project_model.h>
#include <pcl/apps/cloud_composer/properties_model.h>
+#include <QTabWidget>
+
class QItemSelectionModel;
class QTreeView;
-namespace pcl
-{
- namespace cloud_composer
- {
- /** \brief View class for displaying properties of an item
- * \author Jeremie Papon
- * \ingroup cloud_composer
- */
- class ItemInspector : public QTabWidget
- {
- Q_OBJECT
- public:
- ItemInspector (QWidget* parent = nullptr);
-
- public Q_SLOTS:
- void
- setModel (ProjectModel* new_model);
- void
- selectionChanged (const QModelIndex ¤t, const QModelIndex &previous);
- void
- itemChanged (QStandardItem* item);
-
-
-
- private:
- void
- createItemWidgets ();
- /** \brief Stores the state of the current tree view in item_treestate_map_ */
- void
- storeTreeState ();
- /** \brief Restores the state of \param model 's view from item_treestate_map_ */
- void
- restoreTreeState ();
- /** \brief Removes the extra tabs the item might have */
- void
- removeTabs ();
- /** \brief Refreshes the data shown in the current displayed view widget */
- void
- updateView ();
-
- //! The tree object used to display/edit parameters
- QTreeView* parameter_view_;
-
-
- ProjectModel* current_project_model_;
- PropertiesModel* current_item_properties_model_;
- const QItemSelectionModel *current_selection_model_;
- QMap <QString, QWidget*> itemtype_widget_map;
- QMap <QStandardItemModel*, QList <QPersistentModelIndex> > item_treestate_map_;
- };
-
-
- }
-}
+namespace pcl {
+namespace cloud_composer {
+/** \brief View class for displaying properties of an item
+ * \author Jeremie Papon
+ * \ingroup cloud_composer
+ */
+class ItemInspector : public QTabWidget {
+ Q_OBJECT
+public:
+ ItemInspector(QWidget* parent = nullptr);
+
+public Q_SLOTS:
+ void
+ setModel(ProjectModel* new_model);
+ void
+ selectionChanged(const QModelIndex& current, const QModelIndex& previous);
+ void
+ itemChanged(QStandardItem* item);
+
+private:
+ void
+ createItemWidgets();
+ /** \brief Stores the state of the current tree view in item_treestate_map_ */
+ void
+ storeTreeState();
+ /** \brief Restores the state of \param model 's view from item_treestate_map_ */
+ void
+ restoreTreeState();
+ /** \brief Removes the extra tabs the item might have */
+ void
+ removeTabs();
+ /** \brief Refreshes the data shown in the current displayed view widget */
+ void
+ updateView();
+
+ //! The tree object used to display/edit parameters
+ QTreeView* parameter_view_;
+
+ ProjectModel* current_project_model_;
+ PropertiesModel* current_item_properties_model_;
+ const QItemSelectionModel* current_selection_model_;
+ QMap<QString, QWidget*> itemtype_widget_map;
+ QMap<QStandardItemModel*, QList<QPersistentModelIndex>> item_treestate_map_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#pragma once
-#include <pcl/point_types.h>
-#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/apps/cloud_composer/properties_model.h>
+#include <pcl/visualization/pcl_visualizer.h>
+#include <pcl/point_types.h>
+
+static QStringList ITEM_TYPES_STRINGS(QStringList() << "Cloud Composer Item"
+ << "Cloud Item"
+ << "Normals Item"
+ << "FPFH Item");
-static QStringList ITEM_TYPES_STRINGS(QStringList()
- << "Cloud Composer Item"
- << "Cloud Item"
- << "Normals Item"
- << "FPFH Item"
- );
+namespace pcl {
+namespace cloud_composer {
+class PropertiesModel;
+namespace ItemDataRole {
+enum {
+ PROPERTIES = Qt::UserRole,
+ ITEM_ID,
+ CLOUD_BLOB,
+ CLOUD_TEMPLATED,
+ GEOMETRY_HANDLER,
+ COLOR_HANDLER,
+ ORIGIN,
+ ORIENTATION,
+ KD_TREE_SEARCH
+};
+};
+class CloudComposerItem : public QStandardItem {
+public:
+ enum ItemType {
+ CLOUD_COMPOSER_ITEM = QStandardItem::UserType,
+ CLOUD_ITEM,
+ NORMALS_ITEM,
+ FPFH_ITEM
+ };
+
+ CloudComposerItem(const QString& name = "default item");
+ CloudComposerItem(const CloudComposerItem& to_copy);
+ ~CloudComposerItem();
+
+ inline int
+ type() const override
+ {
+ return CLOUD_COMPOSER_ITEM;
+ }
-namespace pcl
-{
- namespace cloud_composer
+ /** \brief Convenience function to get Item's ID String */
+ inline QString
+ getId() const
{
- class PropertiesModel;
- namespace ItemDataRole
- {
- enum
- {
- PROPERTIES = Qt::UserRole,
- ITEM_ID,
- CLOUD_BLOB,
- CLOUD_TEMPLATED,
- GEOMETRY_HANDLER,
- COLOR_HANDLER,
- ORIGIN,
- ORIENTATION,
- KD_TREE_SEARCH
- };
- };
- class CloudComposerItem : public QStandardItem
- {
- public:
-
-
- enum ItemType
- {
- CLOUD_COMPOSER_ITEM = QStandardItem::UserType,
- CLOUD_ITEM,
- NORMALS_ITEM,
- FPFH_ITEM
- };
-
- CloudComposerItem (const QString& name = "default item");
- CloudComposerItem (const CloudComposerItem& to_copy);
- ~CloudComposerItem ();
-
- inline int
- type () const override { return CLOUD_COMPOSER_ITEM; }
-
- /** \brief Convenience function to get Item's ID String */
- inline QString
- getId () const { return data (ItemDataRole::ITEM_ID).toString (); }
-
- /** \brief Convenience function to get Item's Property Pointer */
- inline PropertiesModel*
- getPropertiesModel () const { return properties_; }
-
- /** \brief Returns all children of item type type*/
- QList <CloudComposerItem*>
- getChildren (ItemType type) const;
-
- void
- addChild (CloudComposerItem* item_arg);
-
- CloudComposerItem*
- clone () const override;
-
- // /** \brief Convenience function which pulls out a cloud Ptr of type CloudPtrT */
- // template <typename CloudPtrT>
- // CloudPtrT
- // getCloudPtr () const;
-
- /** \brief Paint View function - reimplement in item subclass if it can be displayed in PCLVisualizer*/
- virtual void
- paintView (pcl::visualization::PCLVisualizer::Ptr vis) const;
-
- /** \brief Remove from View function - reimplement in item subclass if it can be displayed in PCLVisualizer*/
- virtual void
- removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const;
-
- /** \brief Inspector additional tabs paint function - reimplement in item subclass if item has additional tabs to show in Inspector*/
- virtual QMap <QString, QWidget*>
- getInspectorTabs ();
-
- /** \brief The property model calls this when a property changes */
- inline void
- propertyChanged ()
- {
- emitDataChanged ();
- }
-
- virtual bool
- isSanitized () const { return false; }
- protected:
-
- /** \brief Model for storing the properties of the item - pointer kept for convenience */
- PropertiesModel* properties_;
-
- };
-
-
-
- /** \brief Templated helper class for converting QVariant to/from pointer classes */
- template <class T> class VPtr
- {
- public:
- static T* asPtr (const QVariant& v)
- {
- return (static_cast<T *> (v.value<void *> ()));
- }
-
- static QVariant asQVariant (T* ptr)
- {
- return (QVariant::fromValue (static_cast<void*>(ptr)));
- }
- };
-
+ return data(ItemDataRole::ITEM_ID).toString();
}
-}
-using ConstItemList = QList<const pcl::cloud_composer::CloudComposerItem *>;
+ /** \brief Convenience function to get Item's Property Pointer */
+ inline PropertiesModel*
+ getPropertiesModel() const
+ {
+ return properties_;
+ }
+
+ /** \brief Returns all children of item type type*/
+ QList<CloudComposerItem*>
+ getChildren(ItemType type) const;
+
+ void
+ addChild(CloudComposerItem* item_arg);
+
+ CloudComposerItem*
+ clone() const override;
+
+ // /** \brief Convenience function which pulls out a cloud Ptr of type CloudPtrT */
+ // template <typename CloudPtrT>
+ // CloudPtrT
+ // getCloudPtr () const;
+
+ /** \brief Paint View function - reimplement in item subclass if it can be displayed
+ * in PCLVisualizer*/
+ virtual void
+ paintView(pcl::visualization::PCLVisualizer::Ptr vis) const;
+
+ /** \brief Remove from View function - reimplement in item subclass if it can be
+ * displayed in PCLVisualizer*/
+ virtual void
+ removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const;
+
+ /** \brief Inspector additional tabs paint function - reimplement in item subclass if
+ * item has additional tabs to show in Inspector*/
+ virtual QMap<QString, QWidget*>
+ getInspectorTabs();
+
+ /** \brief The property model calls this when a property changes */
+ inline void
+ propertyChanged()
+ {
+ emitDataChanged();
+ }
+
+ virtual bool
+ isSanitized() const
+ {
+ return false;
+ }
+
+protected:
+ /** \brief Model for storing the properties of the item - pointer kept for convenience
+ */
+ PropertiesModel* properties_;
+};
+
+/** \brief Templated helper class for converting QVariant to/from pointer classes */
+template <class T>
+class VPtr {
+public:
+ static T*
+ asPtr(const QVariant& v)
+ {
+ return (static_cast<T*>(v.value<void*>()));
+ }
+
+ static QVariant
+ asQVariant(T* ptr)
+ {
+ return (QVariant::fromValue(static_cast<void*>(ptr)));
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
+
+using ConstItemList = QList<const pcl::cloud_composer::CloudComposerItem*>;
-Q_DECLARE_METATYPE (pcl::cloud_composer::CloudComposerItem);
+Q_DECLARE_METATYPE(pcl::cloud_composer::CloudComposerItem);
#pragma once
-#include <QDebug>
-
#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
-
-#include <pcl/point_types.h>
-#include <pcl/point_cloud.h>
-#include <pcl/PCLPointCloud2.h>
-#include <pcl/memory.h>
-#include <pcl/pcl_macros.h>
#include <pcl/search/kdtree.h>
-#include <pcl/visualization/point_cloud_geometry_handlers.h>
-#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
+#include <pcl/visualization/point_cloud_color_handlers.h>
+#include <pcl/visualization/point_cloud_geometry_handlers.h>
+#include <pcl/memory.h>
+#include <pcl/pcl_macros.h>
+#include <pcl/PCLPointCloud2.h>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
+#include <QDebug>
-//Typedefs to make things sane
-using GeometryHandler = pcl::visualization::PointCloudGeometryHandler<pcl::PCLPointCloud2>;
+// Typedefs to make things sane
+using GeometryHandler =
+ pcl::visualization::PointCloudGeometryHandler<pcl::PCLPointCloud2>;
using ColorHandler = pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>;
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+namespace PointTypeFlags {
+enum PointType {
+ NONE = 0,
+ XYZ = (1 << 0),
+ RGB = (1 << 1),
+ RGBA = (1 << 2),
+ NORMAL = (1 << 3),
+ HSV = (1 << 4),
+ AXIS = (1 << 5),
+};
+}
+class CloudItem : public CloudComposerItem {
+public:
+ // This is needed because we have members which are Vector4f and Quaternionf
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+
+ CloudItem(const QString name,
+ const pcl::PCLPointCloud2::Ptr& cloud_ptr,
+ const Eigen::Vector4f& origin = Eigen::Vector4f(),
+ const Eigen::Quaternionf& orientation = Eigen::Quaternionf(),
+ bool make_templated_cloud = true);
+
+ CloudItem(const CloudItem& to_copy);
+
+ /** \brief This creates a CloudItem from a templated cloud type */
+ template <typename PointT>
+ static CloudItem*
+ createCloudItemFromTemplate(const QString& name,
+ typename PointCloud<PointT>::Ptr cloud_ptr);
+
+ /** \brief virtual data getter which calls QStandardItem::data; used to create
+ * template cloud if not created yet WARNING : This function modifies "this" - it sets
+ * up the templated type if you request one when it doesn't exist yet! It had to
+ * remain const because it is virtual, and we need to keep run-time polymorphism
+ */
+ QVariant
+ data(int role = Qt::UserRole + 1) const override;
+
+ /** \brief Virtual data setter which calls QStandardItem::data; used to ensure that
+ * template_cloud_set_ is set when a templated cloud is added */
+ void
+ setData(const QVariant& value, int role = Qt::UserRole + 1) override;
+
+ inline int
+ type() const override
{
- namespace PointTypeFlags
- {
- enum PointType
- {
- NONE = 0,
- XYZ = (1 << 0),
- RGB = (1 << 1),
- RGBA = (1 << 2),
- NORMAL = (1 << 3),
- HSV = (1 << 4),
- AXIS = (1 << 5),
- };
- }
- class CloudItem : public CloudComposerItem
- {
- public:
-
- //This is needed because we have members which are Vector4f and Quaternionf
- PCL_MAKE_ALIGNED_OPERATOR_NEW
-
- CloudItem (const QString name,
- const pcl::PCLPointCloud2::Ptr& cloud_ptr,
- const Eigen::Vector4f& origin = Eigen::Vector4f (),
- const Eigen::Quaternionf& orientation = Eigen::Quaternionf (),
- bool make_templated_cloud = true);
-
- CloudItem (const CloudItem& to_copy);
-
- /** \brief This creates a CloudItem from a templated cloud type */
- template <typename PointT>
- static CloudItem*
- createCloudItemFromTemplate (const QString& name, typename PointCloud<PointT>::Ptr cloud_ptr);
-
- /** \brief virtual data getter which calls QStandardItem::data; used to create template cloud if not created yet
- * WARNING : This function modifies "this" - it sets up the templated type if you request one when it doesn't exist yet!
- * It had to remain const because it is virtual, and we need to keep run-time polymorphism
- */
- QVariant
- data (int role = Qt::UserRole +1) const override;
-
- /** \brief Virtual data setter which calls QStandardItem::data; used to ensure that template_cloud_set_ is set
- * when a templated cloud is added */
- void
- setData ( const QVariant & value, int role = Qt::UserRole + 1 ) override;
-
- inline int
- type () const override { return CLOUD_ITEM; }
-
- CloudItem*
- clone () const override;
-
- /** \brief Paint View function - puts this cloud item into a PCLVisualizer object*/
- void
- paintView (pcl::visualization::PCLVisualizer::Ptr vis) const override;
-
- /** \brief Remove from View function - removes this cloud from a PCLVisualizer object*/
- void
- removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const override;
-
- /** \brief Initializes and stores a templated PointCloud object with point type matching the blob */
- void
- setTemplateCloudFromBlob ();
-
- int
- getPointType () const { return point_type_; }
-
- template <typename PointT> void
- printNumPoints () const;
-
- bool
- isSanitized () const override { return is_sanitized_; }
- private:
-
- //These are just stored for convenience
- pcl::PCLPointCloud2::Ptr cloud_blob_ptr_;
- ColorHandler::ConstPtr color_handler_;
- GeometryHandler::ConstPtr geometry_handler_;
-
- //We keep actual local copies of these.
- Eigen::Vector4f origin_;
- Eigen::Quaternionf orientation_;
-
- bool template_cloud_set_;
-
- //Internal Storage of the templated type of this cloud
- int point_type_;
-
- bool
- checkIfFinite ();
-
- bool is_sanitized_;
-
- //Helper functions which set the point_type_ based on the current point type
- template <typename PointT> inline void
- setPointType ()
- {
- qCritical () << "CloudItem::setPointType for type with no specialization";
- point_type_ = PointTypeFlags::NONE;
- }
-
- };
-
- template <> inline void
- CloudItem::setPointType <PointXYZ> ()
- {
- point_type_ = PointTypeFlags::XYZ;
- }
- template <> inline void
- CloudItem::setPointType <PointXYZRGB> ()
- {
- point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGB;
- }
- template <> inline void
- CloudItem::setPointType <PointXYZRGBA> ()
- {
- point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGBA;
- }
-
-
+ return CLOUD_ITEM;
}
+
+ CloudItem*
+ clone() const override;
+
+ /** \brief Paint View function - puts this cloud item into a PCLVisualizer object*/
+ void
+ paintView(pcl::visualization::PCLVisualizer::Ptr vis) const override;
+
+ /** \brief Remove from View function - removes this cloud from a PCLVisualizer
+ * object*/
+ void
+ removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const override;
+
+ /** \brief Initializes and stores a templated PointCloud object with point type
+ * matching the blob */
+ void
+ setTemplateCloudFromBlob();
+
+ int
+ getPointType() const
+ {
+ return point_type_;
+ }
+
+ template <typename PointT>
+ void
+ printNumPoints() const;
+
+ bool
+ isSanitized() const override
+ {
+ return is_sanitized_;
+ }
+
+private:
+ // These are just stored for convenience
+ pcl::PCLPointCloud2::Ptr cloud_blob_ptr_;
+ ColorHandler::ConstPtr color_handler_;
+ GeometryHandler::ConstPtr geometry_handler_;
+
+ // We keep actual local copies of these.
+ Eigen::Vector4f origin_;
+ Eigen::Quaternionf orientation_;
+
+ bool template_cloud_set_;
+
+ // Internal Storage of the templated type of this cloud
+ int point_type_;
+
+ bool
+ checkIfFinite();
+
+ bool is_sanitized_;
+
+ // Helper functions which set the point_type_ based on the current point type
+ template <typename PointT>
+ inline void
+ setPointType()
+ {
+ qCritical() << "CloudItem::setPointType for type with no specialization";
+ point_type_ = PointTypeFlags::NONE;
+ }
+};
+
+template <>
+inline void
+CloudItem::setPointType<PointXYZ>()
+{
+ point_type_ = PointTypeFlags::XYZ;
+}
+template <>
+inline void
+CloudItem::setPointType<PointXYZRGB>()
+{
+ point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGB;
}
+template <>
+inline void
+CloudItem::setPointType<PointXYZRGBA>()
+{
+ point_type_ = PointTypeFlags::XYZ | PointTypeFlags::RGBA;
+}
+
+} // namespace cloud_composer
+} // namespace pcl
-//Add PointCloud types to QT MetaType System
-Q_DECLARE_METATYPE (pcl::PCLPointCloud2::ConstPtr);
-Q_DECLARE_METATYPE (GeometryHandler::ConstPtr);
-Q_DECLARE_METATYPE (ColorHandler::ConstPtr);
-Q_DECLARE_METATYPE (Eigen::Vector4f);
-Q_DECLARE_METATYPE (Eigen::Quaternionf);
+// Add PointCloud types to QT MetaType System
+Q_DECLARE_METATYPE(pcl::PCLPointCloud2::ConstPtr);
+Q_DECLARE_METATYPE(GeometryHandler::ConstPtr);
+Q_DECLARE_METATYPE(ColorHandler::ConstPtr);
+Q_DECLARE_METATYPE(Eigen::Vector4f);
+Q_DECLARE_METATYPE(Eigen::Quaternionf);
-Q_DECLARE_METATYPE (pcl::search::KdTree<pcl::PointXYZ>::Ptr);
-Q_DECLARE_METATYPE (pcl::search::KdTree<pcl::PointXYZRGB>::Ptr);
-Q_DECLARE_METATYPE (pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr);
+Q_DECLARE_METATYPE(pcl::search::KdTree<pcl::PointXYZ>::Ptr);
+Q_DECLARE_METATYPE(pcl::search::KdTree<pcl::PointXYZRGB>::Ptr);
+Q_DECLARE_METATYPE(pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr);
-Q_DECLARE_METATYPE (pcl::PointCloud <pcl::PointXYZ>::Ptr);
-Q_DECLARE_METATYPE (pcl::PointCloud <pcl::PointXYZRGB>::Ptr);
-Q_DECLARE_METATYPE (pcl::PointCloud <pcl::PointXYZRGBA>::Ptr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::PointXYZ>::Ptr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::PointXYZRGB>::Ptr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr);
#pragma once
-#include <pcl/point_types.h>
-#include <pcl/features/fpfh.h>
-
#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
-#include <pcl/visualization/qvtk_compatibility.h>
+#include <pcl/features/fpfh.h>
#include <pcl/visualization/pcl_plotter.h>
+#include <pcl/visualization/qvtk_compatibility.h>
+#include <pcl/point_types.h>
+
+namespace pcl {
+namespace cloud_composer {
+
+class FPFHItem : public CloudComposerItem {
+public:
+ FPFHItem(QString name,
+ const pcl::PointCloud<pcl::FPFHSignature33>::Ptr& fpfh_ptr,
+ double radius);
+ FPFHItem(const FPFHItem& to_copy);
-namespace pcl
-{
- namespace cloud_composer
+ inline int
+ type() const override
{
-
- class FPFHItem : public CloudComposerItem
- {
- public:
+ return FPFH_ITEM;
+ }
- FPFHItem (QString name,
- const pcl::PointCloud<pcl::FPFHSignature33>::Ptr& fpfh_ptr,
- double radius);
- FPFHItem (const FPFHItem& to_copy);
-
- inline int
- type () const override { return FPFH_ITEM; }
+ FPFHItem*
+ clone() const override;
- FPFHItem*
- clone () const override;
-
- /** \brief Inspector additional tabs paint function - get the histogram plot widget*/
- QMap <QString, QWidget*>
- getInspectorTabs () override;
-
- private:
- pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfh_ptr_;
- double radius_;
- pcl::visualization::PCLPlotter::Ptr plot_;
- PCLQVTKWidget* qvtk_;
- QWidget *hist_page_;
- };
+ /** \brief Inspector additional tabs paint function - get the histogram plot widget*/
+ QMap<QString, QWidget*>
+ getInspectorTabs() override;
- }
-}
+private:
+ pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfh_ptr_;
+ double radius_;
+ pcl::visualization::PCLPlotter::Ptr plot_;
+ PCLQVTKWidget* qvtk_;
+ QWidget* hist_page_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
-Q_DECLARE_METATYPE (pcl::PointCloud<pcl::FPFHSignature33>::Ptr);
-Q_DECLARE_METATYPE (pcl::PointCloud<pcl::FPFHSignature33>::ConstPtr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::FPFHSignature33>::Ptr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::FPFHSignature33>::ConstPtr);
#pragma once
-#include <pcl/point_types.h>
+#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
#include <pcl/features/normal_3d.h>
+#include <pcl/point_types.h>
-#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
+namespace pcl {
+namespace cloud_composer {
+
+class NormalsItem : public CloudComposerItem {
+public:
+ NormalsItem(QString name,
+ const pcl::PointCloud<pcl::Normal>::Ptr& normals_ptr,
+ double radius);
+ NormalsItem(const NormalsItem& to_copy);
-namespace pcl
-{
- namespace cloud_composer
+ inline int
+ type() const override
{
-
- class NormalsItem : public CloudComposerItem
- {
- public:
+ return NORMALS_ITEM;
+ }
- NormalsItem (QString name,
- const pcl::PointCloud<pcl::Normal>::Ptr& normals_ptr,
- double radius);
- NormalsItem (const NormalsItem& to_copy);
-
- inline int
- type () const override { return NORMALS_ITEM; }
+ NormalsItem*
+ clone() const override;
- NormalsItem*
- clone () const override;
-
- void
- paintView (pcl::visualization::PCLVisualizer::Ptr vis) const override;
-
- /** \brief Remove from View function - removes the normal cloud from a PCLVisualizer object*/
- void
- removeFromView (pcl::visualization::PCLVisualizer::Ptr vis) const override;
-
- private:
- pcl::PointCloud<pcl::Normal>::Ptr normals_ptr_;
+ void
+ paintView(pcl::visualization::PCLVisualizer::Ptr vis) const override;
- };
-
-
-
- }
-}
+ /** \brief Remove from View function - removes the normal cloud from a PCLVisualizer
+ * object*/
+ void
+ removeFromView(pcl::visualization::PCLVisualizer::Ptr vis) const override;
+
+private:
+ pcl::PointCloud<pcl::Normal>::Ptr normals_ptr_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
-Q_DECLARE_METATYPE (pcl::PointCloud<pcl::Normal>::Ptr);
-Q_DECLARE_METATYPE (pcl::PointCloud<pcl::Normal>::ConstPtr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::Normal>::Ptr);
+Q_DECLARE_METATYPE(pcl::PointCloud<pcl::Normal>::ConstPtr);
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class MergeSelection : public MergeCloudTool {
+ Q_OBJECT
+public:
+ MergeSelection(
+ QMap<const CloudItem*, pcl::PointIndices::ConstPtr> selected_item_index_map,
+ QObject* parent = nullptr);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
{
- class MergeSelection : public MergeCloudTool
- {
- Q_OBJECT
- public:
- MergeSelection (QMap <const CloudItem*, pcl::PointIndices::ConstPtr > selected_item_index_map, QObject* parent = nullptr);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Merge Selection Tool";}
-
- QList <const CloudItem*>
- getSelectedItems () { return selected_item_index_map_.keys ();}
-
- template <typename PointT> QList <CloudComposerItem*>
- performTemplatedAction (const QList <const CloudComposerItem*>& input_data);
-
- private:
- QMap <const CloudItem*, pcl::PointIndices::ConstPtr > selected_item_index_map_;
- };
+ return "Merge Selection Tool";
+ }
+ QList<const CloudItem*>
+ getSelectedItems()
+ {
+ return selected_item_index_map_.keys();
}
-}
+
+ template <typename PointT>
+ QList<CloudComposerItem*>
+ performTemplatedAction(const QList<const CloudComposerItem*>& input_data);
+
+private:
+ QMap<const CloudItem*, pcl::PointIndices::ConstPtr> selected_item_index_map_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <vtkInteractorStyleTrackballActor.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+
+class ClickTrackballStyleInteractor : public vtkInteractorStyleTrackballActor {
+public:
+ static ClickTrackballStyleInteractor*
+ New();
+ vtkTypeMacro(ClickTrackballStyleInteractor, vtkInteractorStyleTrackballActor);
+
+ ClickTrackballStyleInteractor();
+
+ /** \brief Pass a pointer to the actor map
+ * \param[in] actors the actor map that will be used with this style
+ */
+ inline void
+ setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors)
+ {
+ actors_ = actors;
+ }
+
+ /** \brief Get the cloud actor map pointer. */
+ inline pcl::visualization::CloudActorMapPtr
+ getCloudActorMap() const
+ {
+ return (actors_);
+ }
+
+ /** \brief Pass a set of renderers to the interactor style.
+ * \param[in] rens the vtkRendererCollection to use
+ */
+ void
+ setRendererCollection(vtkSmartPointer<vtkRendererCollection>& rens)
+ {
+ renderers_ = rens;
+ }
+
+ /** \brief Function called on left mouse button release, ie, end of rectangular drag
+ */
+ void
+ OnLeftButtonDown() override;
+
+ /** \brief Function called on left mouse button release, ie, end of rectangular drag
+ */
+ void
+ OnLeftButtonUp() override;
+
+ void
+ OnRightButtonDown() override;
+
+ void
+ OnRightButtonUp() override;
+
+ /** \brief Event emitted once a valid selection has been made */
+ int manipulation_complete_event_;
+
+ inline void
+ setProjectModel(ProjectModel* model)
{
-
- class ClickTrackballStyleInteractor : public vtkInteractorStyleTrackballActor
- {
- public:
- static ClickTrackballStyleInteractor* New();
- vtkTypeMacro(ClickTrackballStyleInteractor,vtkInteractorStyleTrackballActor);
-
- ClickTrackballStyleInteractor ();
-
- /** \brief Pass a pointer to the actor map
- * \param[in] actors the actor map that will be used with this style
- */
- inline void
- setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; }
-
- /** \brief Get the cloud actor map pointer. */
- inline pcl::visualization::CloudActorMapPtr
- getCloudActorMap () const { return (actors_); }
-
- /** \brief Pass a set of renderers to the interactor style.
- * \param[in] rens the vtkRendererCollection to use
- */
- void
- setRendererCollection (vtkSmartPointer<vtkRendererCollection> &rens) { renderers_ = rens; }
-
- /** \brief Function called on left mouse button release, ie, end of rectangular drag */
- void
- OnLeftButtonDown () override;
-
- /** \brief Function called on left mouse button release, ie, end of rectangular drag */
- void
- OnLeftButtonUp () override;
-
- void
- OnRightButtonDown () override;
-
- void
- OnRightButtonUp () override;
-
- /** \brief Event emitted once a valid selection has been made */
- int manipulation_complete_event_;
-
- inline void
- setProjectModel (ProjectModel* model) { model_ = model; }
- private:
-
-
- /** \brief Actor map stored internally. */
- pcl::visualization::CloudActorMapPtr actors_;
-
- /** \brief Collection of vtkRenderers stored internally. */
- vtkSmartPointer<vtkRendererCollection> renderers_;
-
- /** \brief Internal Pointer to Project Model */
- ProjectModel* model_;
-
- vtkSmartPointer<vtkMatrix4x4> start_matrix_;
- vtkSmartPointer<vtkMatrix4x4> end_matrix_;
-
- vtkSmartPointer<vtkTransform> transform_;
-
- };
-
+ model_ = model;
}
-
-}
+
+private:
+ /** \brief Actor map stored internally. */
+ pcl::visualization::CloudActorMapPtr actors_;
+
+ /** \brief Collection of vtkRenderers stored internally. */
+ vtkSmartPointer<vtkRendererCollection> renderers_;
+
+ /** \brief Internal Pointer to Project Model */
+ ProjectModel* model_;
+
+ vtkSmartPointer<vtkMatrix4x4> start_matrix_;
+ vtkSmartPointer<vtkMatrix4x4> end_matrix_;
+
+ vtkSmartPointer<vtkTransform> transform_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#pragma once
-#include <QMap>
-
-#include <pcl/visualization/interactor_style.h>
#include <pcl/visualization/common/actor_map.h>
#include <pcl/visualization/common/ren_win_interact_map.h>
+#include <pcl/visualization/interactor_style.h>
#include <pcl/visualization/pcl_visualizer.h>
-#include <vtkSmartPointer.h>
+#include <QMap>
+
#include <vtkAreaPicker.h>
-#include <vtkPointPicker.h>
-#include <vtkRenderWindowInteractor.h>
#include <vtkCommand.h>
-#include <vtkRendererCollection.h>
#include <vtkInteractorStyle.h>
+#include <vtkPointPicker.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkSmartPointer.h>
class QVTKWidget;
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+namespace interactor_styles {
+enum INTERACTOR_STYLES {
+ PCL_VISUALIZER = 0,
+ RECTANGULAR_FRUSTUM,
+ SELECTED_TRACKBALL,
+ CLICK_TRACKBALL
+};
+}
+namespace interactor_events {
+enum {
+ SELECTION_COMPLETE_EVENT = vtkCommand::UserEvent + 1,
+ MANIPULATION_COMPLETE_EVENT
+};
+};
+
+class RectangularFrustumSelector;
+class SelectedTrackballStyleInteractor;
+class ClickTrackballStyleInteractor;
+class ProjectModel;
+
+class InteractorStyleSwitch : public vtkInteractorStyle {
+public:
+ static InteractorStyleSwitch*
+ New();
+ vtkTypeMacro(InteractorStyleSwitch, vtkInteractorStyle);
+
+ InteractorStyleSwitch();
+
+ void
+ SetInteractor(vtkRenderWindowInteractor* iren) override;
+
+ vtkGetObjectMacro(current_style_, vtkInteractorStyle);
+
+ void
+ initializeInteractorStyles(pcl::visualization::PCLVisualizer::Ptr vis,
+ ProjectModel* model);
+
+ inline void
+ setQVTKWidget(QVTKWidget* qvtk)
{
- namespace interactor_styles
- {
- enum INTERACTOR_STYLES
- {
- PCL_VISUALIZER = 0,
- RECTANGULAR_FRUSTUM,
- SELECTED_TRACKBALL,
- CLICK_TRACKBALL
- };
- }
- namespace interactor_events
- {
- enum
- {
- SELECTION_COMPLETE_EVENT = vtkCommand::UserEvent + 1,
- MANIPULATION_COMPLETE_EVENT
- };
- };
-
- class RectangularFrustumSelector;
- class SelectedTrackballStyleInteractor;
- class ClickTrackballStyleInteractor;
- class ProjectModel;
-
- class InteractorStyleSwitch : public vtkInteractorStyle
- {
- public:
- static InteractorStyleSwitch *New();
- vtkTypeMacro(InteractorStyleSwitch, vtkInteractorStyle);
-
- InteractorStyleSwitch();
-
- void
- SetInteractor(vtkRenderWindowInteractor *iren) override;
-
- vtkGetObjectMacro(current_style_, vtkInteractorStyle);
-
- void
- initializeInteractorStyles (pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model);
-
- inline void
- setQVTKWidget (QVTKWidget* qvtk) { qvtk_ = qvtk; }
-
- void
- setCurrentInteractorStyle (interactor_styles::INTERACTOR_STYLES interactor_style);
-
- // vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle>
- // getPCLVisInteractorStyle () { return pcl_vis_style_; }
-
- inline vtkSmartPointer <vtkInteractorStyle>
- getInteractorStyle (const interactor_styles::INTERACTOR_STYLES interactor_style) const
- { return name_to_style_map_.value (interactor_style); }
-
-
- void SetDefaultRenderer(vtkRenderer*) override;
-
- void SetCurrentRenderer(vtkRenderer*) override;
-
- void
- OnLeave () override;
-
- protected:
- void
- setCurrentStyle();
-
- QMap <interactor_styles::INTERACTOR_STYLES, vtkSmartPointer <vtkInteractorStyle> > name_to_style_map_;
-
-
- vtkRenderWindowInteractor* render_window_interactor_;
- vtkSmartPointer<vtkRendererCollection> rens_;
-
- vtkInteractorStyle* current_style_;
- vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle> pcl_vis_style_;
- vtkSmartPointer<RectangularFrustumSelector> rectangular_frustum_selector_;
-
- vtkSmartPointer<SelectedTrackballStyleInteractor> selected_trackball_interactor_style_;
-
- vtkSmartPointer<ClickTrackballStyleInteractor> click_trackball_interactor_style_;
- vtkSmartPointer<vtkAreaPicker> area_picker_;
- vtkSmartPointer<vtkPointPicker> point_picker_;
-
- /** \brief Internal pointer to QVTKWidget that this Switch works with */
- QVTKWidget* qvtk_;
- /** \brief Internal pointer to PCLVisualizer that this Switch works with */
- pcl::visualization::PCLVisualizer::Ptr vis_;
- private:
- InteractorStyleSwitch(const InteractorStyleSwitch&); // Not implemented.
- void operator=(const InteractorStyleSwitch&); // Not implemented.
- ProjectModel* project_model_;
- };
-
+ qvtk_ = qvtk;
}
-
-}
+
+ void
+ setCurrentInteractorStyle(interactor_styles::INTERACTOR_STYLES interactor_style);
+
+ // vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle>
+ // getPCLVisInteractorStyle () { return pcl_vis_style_; }
+
+ inline vtkSmartPointer<vtkInteractorStyle>
+ getInteractorStyle(const interactor_styles::INTERACTOR_STYLES interactor_style) const
+ {
+ return name_to_style_map_.value(interactor_style);
+ }
+
+ void
+ SetDefaultRenderer(vtkRenderer*) override;
+
+ void
+ SetCurrentRenderer(vtkRenderer*) override;
+
+ void
+ OnLeave() override;
+
+protected:
+ void
+ setCurrentStyle();
+
+ QMap<interactor_styles::INTERACTOR_STYLES, vtkSmartPointer<vtkInteractorStyle>>
+ name_to_style_map_;
+
+ vtkRenderWindowInteractor* render_window_interactor_;
+ vtkSmartPointer<vtkRendererCollection> rens_;
+
+ vtkInteractorStyle* current_style_;
+ vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle> pcl_vis_style_;
+ vtkSmartPointer<RectangularFrustumSelector> rectangular_frustum_selector_;
+
+ vtkSmartPointer<SelectedTrackballStyleInteractor>
+ selected_trackball_interactor_style_;
+
+ vtkSmartPointer<ClickTrackballStyleInteractor> click_trackball_interactor_style_;
+ vtkSmartPointer<vtkAreaPicker> area_picker_;
+ vtkSmartPointer<vtkPointPicker> point_picker_;
+
+ /** \brief Internal pointer to QVTKWidget that this Switch works with */
+ QVTKWidget* qvtk_;
+ /** \brief Internal pointer to PCLVisualizer that this Switch works with */
+ pcl::visualization::PCLVisualizer::Ptr vis_;
+
+private:
+ InteractorStyleSwitch(const InteractorStyleSwitch&); // Not implemented.
+ void
+ operator=(const InteractorStyleSwitch&); // Not implemented.
+ ProjectModel* project_model_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+
+class ManipulationEvent {
+
+public:
+ ManipulationEvent() {}
+
+ void
+ addManipulation(const QString& id,
+ const vtkSmartPointer<vtkMatrix4x4>& start,
+ const vtkSmartPointer<vtkMatrix4x4>& end);
+
+ inline QMap<QString, vtkSmartPointer<vtkMatrix4x4>>
+ getStartMap() const
+ {
+ return id_start_map_;
+ }
+
+ inline QMap<QString, vtkSmartPointer<vtkMatrix4x4>>
+ getEndMap() const
{
-
-
- class ManipulationEvent
- {
-
- public:
- ManipulationEvent ()
- {}
-
- void
- addManipulation (const QString& id, const vtkSmartPointer<vtkMatrix4x4>& start, const vtkSmartPointer<vtkMatrix4x4>& end);
-
- inline QMap <QString, vtkSmartPointer<vtkMatrix4x4> >
- getStartMap () const { return id_start_map_;}
-
- inline QMap <QString, vtkSmartPointer<vtkMatrix4x4> >
- getEndMap () const { return id_end_map_;}
-
-
- private:
- QMap <QString, vtkSmartPointer<vtkMatrix4x4> > id_start_map_;
- QMap <QString, vtkSmartPointer<vtkMatrix4x4> > id_end_map_;
-
- };
-
+ return id_end_map_;
}
-
-}
+
+private:
+ QMap<QString, vtkSmartPointer<vtkMatrix4x4>> id_start_map_;
+ QMap<QString, vtkSmartPointer<vtkMatrix4x4>> id_end_map_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
-#include <vtkSmartPointer.h>
-#include <vtkRendererCollection.h>
#include <vtkInteractorStyleRubberBandPick.h>
+#include <vtkRendererCollection.h>
+#include <vtkSmartPointer.h>
-namespace pcl
-{
- namespace cloud_composer
- {
-
- class RectangularFrustumSelector : public vtkInteractorStyleRubberBandPick
- {
- public:
- static RectangularFrustumSelector* New();
- vtkTypeMacro(RectangularFrustumSelector,vtkInteractorStyleRubberBandPick);
-
- RectangularFrustumSelector ();
-
- /** \brief Pass a pointer to the actor map
- * \param[in] actors the actor map that will be used with this style
- */
- inline void
- setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; }
+namespace pcl {
+namespace cloud_composer {
- /** \brief Get the cloud actor map pointer. */
- inline pcl::visualization::CloudActorMapPtr
- getCloudActorMap () const { return (actors_); }
+class RectangularFrustumSelector : public vtkInteractorStyleRubberBandPick {
+public:
+ static RectangularFrustumSelector*
+ New();
+ vtkTypeMacro(RectangularFrustumSelector, vtkInteractorStyleRubberBandPick);
- /** \brief Pass a set of renderers to the interactor style.
- * \param[in] rens the vtkRendererCollection to use
- */
- void
- setRendererCollection (vtkSmartPointer<vtkRendererCollection> &rens) { renderers_ = rens; }
+ RectangularFrustumSelector();
- /** \brief Function called on left mouse button release, ie, end of rectangular drag */
- void
- OnLeftButtonUp () override;
+ /** \brief Pass a pointer to the actor map
+ * \param[in] actors the actor map that will be used with this style
+ */
+ inline void
+ setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors)
+ {
+ actors_ = actors;
+ }
- /** \brief Event emitted once a valid selection has been made */
- int selection_complete_event_;
- private:
+ /** \brief Get the cloud actor map pointer. */
+ inline pcl::visualization::CloudActorMapPtr
+ getCloudActorMap() const
+ {
+ return (actors_);
+ }
-
- /** \brief Actor map stored internally. */
- pcl::visualization::CloudActorMapPtr actors_;
-
- /** \brief Collection of vtkRenderers stored internally. */
- vtkSmartPointer<vtkRendererCollection> renderers_;
- };
-
+ /** \brief Pass a set of renderers to the interactor style.
+ * \param[in] rens the vtkRendererCollection to use
+ */
+ void
+ setRendererCollection(vtkSmartPointer<vtkRendererCollection>& rens)
+ {
+ renderers_ = rens;
}
-
-}
+
+ /** \brief Function called on left mouse button release, ie, end of rectangular drag
+ */
+ void
+ OnLeftButtonUp() override;
+
+ /** \brief Event emitted once a valid selection has been made */
+ int selection_complete_event_;
+
+private:
+ /** \brief Actor map stored internally. */
+ pcl::visualization::CloudActorMapPtr actors_;
+
+ /** \brief Collection of vtkRenderers stored internally. */
+ vtkSmartPointer<vtkRendererCollection> renderers_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
#include <vtkInteractorStyleTrackballActor.h>
-#include <vtkSmartPointer.h>
#include <vtkMatrix4x4.h>
+#include <vtkSmartPointer.h>
+
+namespace pcl {
+namespace cloud_composer {
+
+class SelectedTrackballStyleInteractor : public vtkInteractorStyleTrackballActor {
+public:
+ static SelectedTrackballStyleInteractor*
+ New();
+ vtkTypeMacro(SelectedTrackballStyleInteractor, vtkInteractorStyleTrackballActor);
+
+ SelectedTrackballStyleInteractor();
+
+ /** \brief Pass a pointer to the actor map
+ * \param[in] actors the actor map that will be used with this style
+ */
+ inline void
+ setCloudActorMap(const pcl::visualization::CloudActorMapPtr& actors)
+ {
+ actors_ = actors;
+ }
+
+ /** \brief Get the cloud actor map pointer. */
+ inline pcl::visualization::CloudActorMapPtr
+ getCloudActorMap() const
+ {
+ return (actors_);
+ }
-namespace pcl
-{
- namespace cloud_composer
+ /** \brief Pass a set of renderers to the interactor style.
+ * \param[in] rens the vtkRendererCollection to use
+ */
+ void
+ setRendererCollection(vtkSmartPointer<vtkRendererCollection>& rens)
{
-
- class SelectedTrackballStyleInteractor : public vtkInteractorStyleTrackballActor
- {
- public:
- static SelectedTrackballStyleInteractor* New();
- vtkTypeMacro(SelectedTrackballStyleInteractor,vtkInteractorStyleTrackballActor);
-
- SelectedTrackballStyleInteractor ();
-
- /** \brief Pass a pointer to the actor map
- * \param[in] actors the actor map that will be used with this style
- */
- inline void
- setCloudActorMap (const pcl::visualization::CloudActorMapPtr &actors) { actors_ = actors; }
-
- /** \brief Get the cloud actor map pointer. */
- inline pcl::visualization::CloudActorMapPtr
- getCloudActorMap () const { return (actors_); }
-
- /** \brief Pass a set of renderers to the interactor style.
- * \param[in] rens the vtkRendererCollection to use
- */
- void
- setRendererCollection (vtkSmartPointer<vtkRendererCollection> &rens) { renderers_ = rens; }
-
- /** \brief Function called on left mouse button click, ie, beginning of trackball */
- void
- OnLeftButtonDown () override;
-
- void
- OnRightButtonDown () override;
-
- /** \brief Function called on left mouse button release, ie, end of trackball*/
- void
- OnLeftButtonUp () override;
-
- void
- OnRightButtonUp () override;
-
- void
- Rotate() override;
- void
- Spin() override;
- void
- Pan() override;
- void
- UniformScale() override;
-
- /** \brief Event emitted once a valid selection has been made */
- int manipulation_complete_event_;
-
- inline void
- setProjectModel (ProjectModel* model) { model_ = model; }
- private:
-
- void
- setSelectedActors ();
-
- /** \brief Actor map stored internally. */
- pcl::visualization::CloudActorMapPtr actors_;
-
- /** \brief Collection of vtkRenderers stored internally. */
- vtkSmartPointer<vtkRendererCollection> renderers_;
-
- /** \brief Internal Pointer to Project Model */
- ProjectModel* model_;
-
- QMap <QString, vtkSmartPointer<vtkMatrix4x4> > start_matrix_map_;
- QMap <QString, vtkLODActor*> selected_actors_map_;
-
- };
-
+ renderers_ = rens;
}
-
-}
+
+ /** \brief Function called on left mouse button click, ie, beginning of trackball */
+ void
+ OnLeftButtonDown() override;
+
+ void
+ OnRightButtonDown() override;
+
+ /** \brief Function called on left mouse button release, ie, end of trackball*/
+ void
+ OnLeftButtonUp() override;
+
+ void
+ OnRightButtonUp() override;
+
+ void
+ Rotate() override;
+ void
+ Spin() override;
+ void
+ Pan() override;
+ void
+ UniformScale() override;
+
+ /** \brief Event emitted once a valid selection has been made */
+ int manipulation_complete_event_;
+
+ inline void
+ setProjectModel(ProjectModel* model)
+ {
+ model_ = model;
+ }
+
+private:
+ void
+ setSelectedActors();
+
+ /** \brief Actor map stored internally. */
+ pcl::visualization::CloudActorMapPtr actors_;
+
+ /** \brief Collection of vtkRenderers stored internally. */
+ vtkSmartPointer<vtkRendererCollection> renderers_;
+
+ /** \brief Internal Pointer to Project Model */
+ ProjectModel* model_;
+
+ QMap<QString, vtkSmartPointer<vtkMatrix4x4>> start_matrix_map_;
+ QMap<QString, vtkLODActor*> selected_actors_map_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-#include <vtkSmartPointer.h>
-#include <vtkPolyData.h>
#include <vtkActor.h>
#include <vtkDataSetMapper.h>
+#include <vtkPolyData.h>
#include <vtkRenderer.h>
+#include <vtkSmartPointer.h>
+
+namespace pcl {
+namespace cloud_composer {
+class RectangularFrustumSelector;
+
+class SelectionEvent {
+
+public:
+ SelectionEvent(vtkSmartPointer<vtkPolyData> selected_points,
+ vtkSmartPointer<vtkActor> selected_actor,
+ vtkSmartPointer<vtkDataSetMapper> selected_mapper,
+ QMap<QString, vtkPolyData*> id_selected_map,
+ vtkRenderer* renderer)
+ : selected_points_(std::move(selected_points))
+ , selected_actor_(std::move(selected_actor))
+ , selected_mapper_(std::move(selected_mapper))
+ , id_selected_data_map_(std::move(id_selected_map))
+ , renderer_(renderer)
+ {}
+
+ ~SelectionEvent();
+
+ inline vtkIdType
+ getNumPoints() const
+ {
+ return selected_points_->GetNumberOfPoints();
+ }
-namespace pcl
-{
- namespace cloud_composer
+ vtkSmartPointer<vtkPolyData>
+ getPolyData() const
{
- class RectangularFrustumSelector;
-
- class SelectionEvent
- {
-
- public:
- SelectionEvent (vtkSmartPointer <vtkPolyData> selected_points, vtkSmartPointer<vtkActor> selected_actor, vtkSmartPointer<vtkDataSetMapper> selected_mapper, QMap < QString, vtkPolyData* > id_selected_map, vtkRenderer* renderer)
- : selected_points_ (std::move(selected_points))
- , selected_actor_ (std::move(selected_actor))
- , selected_mapper_ (std::move(selected_mapper))
- , id_selected_data_map_ (std::move(id_selected_map))
- , renderer_ (renderer)
- {}
-
- ~SelectionEvent ();
-
- inline vtkIdType
- getNumPoints () const { return selected_points_->GetNumberOfPoints (); }
-
- vtkSmartPointer <vtkPolyData>
- getPolyData () const { return selected_points_; }
-
- vtkSmartPointer <vtkDataSetMapper>
- getMapper () const { return selected_mapper_; }
-
- vtkSmartPointer <vtkActor>
- getActor () const { return selected_actor_; }
-
- void
- findIndicesInItem (CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices);
-
- private:
-
- vtkSmartPointer <vtkPolyData> selected_points_;
- vtkSmartPointer<vtkActor> selected_actor_;
- vtkSmartPointer<vtkDataSetMapper> selected_mapper_;
- QMap < QString, vtkPolyData* > id_selected_data_map_;
- vtkRenderer* renderer_;
-
- };
-
+ return selected_points_;
}
-
-}
+
+ vtkSmartPointer<vtkDataSetMapper>
+ getMapper() const
+ {
+ return selected_mapper_;
+ }
+
+ vtkSmartPointer<vtkActor>
+ getActor() const
+ {
+ return selected_actor_;
+ }
+
+ void
+ findIndicesInItem(CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices);
+
+private:
+ vtkSmartPointer<vtkPolyData> selected_points_;
+ vtkSmartPointer<vtkActor> selected_actor_;
+ vtkSmartPointer<vtkDataSetMapper> selected_mapper_;
+ QMap<QString, vtkPolyData*> id_selected_data_map_;
+ vtkRenderer* renderer_;
+};
+
+} // namespace cloud_composer
+
+} // namespace pcl
#pragma once
-#include <vtkSmartPointer.h>
-#include <vtkCamera.h>
-
-#include <pcl/io/pcd_io.h>
-
#include <pcl/apps/cloud_composer/commands.h>
-#include <pcl/apps/cloud_composer/point_selectors/selection_event.h>
-#include <pcl/apps/cloud_composer/point_selectors/manipulation_event.h>
#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
+#include <pcl/apps/cloud_composer/point_selectors/manipulation_event.h>
+#include <pcl/apps/cloud_composer/point_selectors/selection_event.h>
+#include <pcl/io/pcd_io.h>
#include <QDir>
+#include <vtkCamera.h>
+#include <vtkSmartPointer.h>
+
class QItemSelection;
class QItemSelectionModel;
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class CloudCommand;
+class AbstractTool;
+class WorkQueue;
+class CloudComposerItem;
+class CloudView;
+class InteractorStyleSwitch;
+
+class ProjectModel : public QStandardItemModel {
+ Q_OBJECT
+
+public:
+ ProjectModel(QObject* parent = nullptr);
+ ProjectModel(const ProjectModel& to_copy);
+ ~ProjectModel();
+
+ ProjectModel(QString project_name, QObject* parent = nullptr);
+
+ inline const QString
+ getName()
+ {
+ return horizontalHeaderItem(0)->text();
+ }
+
+ inline QUndoStack*
+ getUndoStack()
{
- class CloudCommand;
- class AbstractTool;
- class WorkQueue;
- class CloudComposerItem;
- class CloudView;
- class InteractorStyleSwitch;
-
- class ProjectModel : public QStandardItemModel
- {
- Q_OBJECT
-
- public:
- ProjectModel (QObject *parent = nullptr);
- ProjectModel (const ProjectModel& to_copy);
- ~ProjectModel ();
-
- ProjectModel (QString project_name, QObject *parent = nullptr);
-
- inline const QString
- getName () { return horizontalHeaderItem (0)->text (); }
-
- inline QUndoStack*
- getUndoStack () { return undo_stack_; }
-
- /** \brief Sets the name of the project using the horizontalHeaderItem */
- void
- setName (const QString& new_name);
-
- /** \brief Returns the selection model which is used for this project */
- inline QItemSelectionModel*
- getSelectionModel ()
- {
- return selection_model_;
- }
-
-
-
- /** \brief Takes tool object issues signal to work queue to take control of it */
- void
- enqueueToolAction (AbstractTool* tool);
-
- /** \brief Helper function which inserts the item into this model and makes connections for properties */
- void
- insertNewCloudComposerItem (CloudComposerItem* new_item, QStandardItem* parent_item);
-
- /** \brief Sets the CloudView that this project is rendering in */
- void
- setCloudView (CloudView* view);
-
- /** \brief This sets the selection for points which have been selected in the QVTKWindow */
- void
- setPointSelection (const std::shared_ptr<SelectionEvent>& selected_event);
-
- /** \brief This is invoked to perform the manipulations specified on the model */
- void
- manipulateClouds (const std::shared_ptr<ManipulationEvent>& manip_event);
- public Q_SLOTS:
- void
- commandCompleted (CloudCommand* command);
-
- void
- clearSelection ();
-
- void
- deleteSelectedItems ();
-
- /** \brief Loads from file and inserts a new pointcloud into the model */
- void
- insertNewCloudFromFile ();
-
- /** \brief Loads from rgb and depth file and inserts a new pointcloud into the model */
- void
- insertNewCloudFromRGBandDepth ();
-
- /** \brief Opens a file dialog and saves selected cloud to file */
- void
- saveSelectedCloudToFile ();
-
- /** \brief This emits all the state signals, which updates the GUI action button status (enabled/disabled)" */
- void
- emitAllStateSignals ();
-
- /** \brief This sets whether the CloudView for this project shows axes */
- void
- setAxisVisibility (bool visible);
-
- /** \brief Slot called when the mouse style selected in the GUI changes */
- void
- mouseStyleChanged (QAction* new_style_action);
-
- /** \brief Slot Called whenever the item selection_model_ changes */
- void
- itemSelectionChanged ( const QItemSelection &, const QItemSelection &);
-
- /** \brief Creates a new cloud from the selected items and points */
- void
- createNewCloudFromSelection ();
-
- /** \brief Selects all items in the model */
- void
- selectAllItems (QStandardItem* item = nullptr );
- Q_SIGNALS:
- void
- enqueueNewAction (AbstractTool* tool, ConstItemList data);
-
- /** \brief Catch-all signal emitted whenever the model changes */
- void
- modelChanged ();
-
- void
- axisVisible (const bool axis_visible);
-
- void
- deleteAvailable (bool can_delete);
-
- void
- newCloudFromSelectionAvailable (bool can_create);
-
- void
- mouseStyleState (interactor_styles::INTERACTOR_STYLES);
-
- private:
- /** \brief Checks to see if selection contains only CloudItem s */
- bool
- onlyCloudItemsSelected ();
-
- QItemSelectionModel* selection_model_;
- QMap <QString, int> name_to_type_map_;
- QUndoStack* undo_stack_;
- WorkQueue* work_queue_;
- QThread* work_thread_;
- CloudView* cloud_view_;
-
- /** \brief Stores last directory used in file read/write operations */
- QDir last_directory_;
-
- //Variables for toggle action status
- bool axis_visible_;
- QMap <interactor_styles::INTERACTOR_STYLES, bool> selected_style_map_;
- /** \brief Internal helper function for updating map */
- void
- setSelectedStyle (interactor_styles::INTERACTOR_STYLES style);
-
- /** \brief Internal pointer storing the last selection event arriving from vtk */
- std::shared_ptr<SelectionEvent> selection_event_;
- /** \brief Map which stores which cloud items and indices were selected in the selection_event_ */
- QMap <CloudItem*, pcl::PointIndices::Ptr > selected_item_index_map_;
- };
+ return undo_stack_;
}
-}
-Q_DECLARE_METATYPE (pcl::cloud_composer::ProjectModel);
-Q_DECLARE_METATYPE (pcl::cloud_composer::interactor_styles::INTERACTOR_STYLES);
+ /** \brief Sets the name of the project using the horizontalHeaderItem */
+ void
+ setName(const QString& new_name);
+
+ /** \brief Returns the selection model which is used for this project */
+ inline QItemSelectionModel*
+ getSelectionModel()
+ {
+ return selection_model_;
+ }
+
+ /** \brief Takes tool object issues signal to work queue to take control of it */
+ void
+ enqueueToolAction(AbstractTool* tool);
+
+ /** \brief Helper function which inserts the item into this model and makes
+ * connections for properties */
+ void
+ insertNewCloudComposerItem(CloudComposerItem* new_item, QStandardItem* parent_item);
+
+ /** \brief Sets the CloudView that this project is rendering in */
+ void
+ setCloudView(CloudView* view);
+
+ /** \brief This sets the selection for points which have been selected in the
+ * QVTKWindow */
+ void
+ setPointSelection(const std::shared_ptr<SelectionEvent>& selected_event);
+
+ /** \brief This is invoked to perform the manipulations specified on the model */
+ void
+ manipulateClouds(const std::shared_ptr<ManipulationEvent>& manip_event);
+public Q_SLOTS:
+ void
+ commandCompleted(CloudCommand* command);
+
+ void
+ clearSelection();
+
+ void
+ deleteSelectedItems();
+
+ /** \brief Loads from file and inserts a new pointcloud into the model */
+ void
+ insertNewCloudFromFile();
+
+ /** \brief Loads from rgb and depth file and inserts a new pointcloud into the model
+ */
+ void
+ insertNewCloudFromRGBandDepth();
+
+ /** \brief Opens a file dialog and saves selected cloud to file */
+ void
+ saveSelectedCloudToFile();
+
+ /** \brief This emits all the state signals, which updates the GUI action button
+ * status (enabled/disabled)" */
+ void
+ emitAllStateSignals();
+
+ /** \brief This sets whether the CloudView for this project shows axes */
+ void
+ setAxisVisibility(bool visible);
+
+ /** \brief Slot called when the mouse style selected in the GUI changes */
+ void
+ mouseStyleChanged(QAction* new_style_action);
+
+ /** \brief Slot Called whenever the item selection_model_ changes */
+ void
+ itemSelectionChanged(const QItemSelection&, const QItemSelection&);
+
+ /** \brief Creates a new cloud from the selected items and points */
+ void
+ createNewCloudFromSelection();
+
+ /** \brief Selects all items in the model */
+ void
+ selectAllItems(QStandardItem* item = nullptr);
+Q_SIGNALS:
+ void
+ enqueueNewAction(AbstractTool* tool, ConstItemList data);
+
+ /** \brief Catch-all signal emitted whenever the model changes */
+ void
+ modelChanged();
+
+ void
+ axisVisible(const bool axis_visible);
+
+ void
+ deleteAvailable(bool can_delete);
+
+ void
+ newCloudFromSelectionAvailable(bool can_create);
+
+ void mouseStyleState(interactor_styles::INTERACTOR_STYLES);
+
+private:
+ /** \brief Checks to see if selection contains only CloudItem s */
+ bool
+ onlyCloudItemsSelected();
+
+ QItemSelectionModel* selection_model_;
+ QMap<QString, int> name_to_type_map_;
+ QUndoStack* undo_stack_;
+ WorkQueue* work_queue_;
+ QThread* work_thread_;
+ CloudView* cloud_view_;
+
+ /** \brief Stores last directory used in file read/write operations */
+ QDir last_directory_;
+
+ // Variables for toggle action status
+ bool axis_visible_;
+ QMap<interactor_styles::INTERACTOR_STYLES, bool> selected_style_map_;
+ /** \brief Internal helper function for updating map */
+ void
+ setSelectedStyle(interactor_styles::INTERACTOR_STYLES style);
+
+ /** \brief Internal pointer storing the last selection event arriving from vtk */
+ std::shared_ptr<SelectionEvent> selection_event_;
+ /** \brief Map which stores which cloud items and indices were selected in the
+ * selection_event_ */
+ QMap<CloudItem*, pcl::PointIndices::Ptr> selected_item_index_map_;
+};
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(pcl::cloud_composer::ProjectModel);
+Q_DECLARE_METATYPE(pcl::cloud_composer::interactor_styles::INTERACTOR_STYLES);
#include <QStandardItemModel>
-namespace pcl
-{
- namespace cloud_composer
- {
- class CloudComposerItem;
- class PropertiesModel : public QStandardItemModel
- {
- Q_OBJECT
- public:
-
- /** \brief Constructor used for tool parameters */
- PropertiesModel (QObject *parent = nullptr);
- /** \brief Constructor used for item parameters */
- PropertiesModel (CloudComposerItem* parent_item, QObject *parent = nullptr);
- PropertiesModel (const PropertiesModel& to_copy);
-
- /** \brief Helper function for adding a new property */
- void
- addProperty (const QString& prop_name, const QVariant& value, const Qt::ItemFlags flags = Qt::ItemIsSelectable, const QString& category = "");
-
- /** \brief Helper function for adding a new property category */
- void
- addCategory (const QString& category_name);
-
- /** \brief Helper function to get a property */
- QVariant
- getProperty (const QString& prop_name) const;
-
- void
- copyProperties (const PropertiesModel* to_copy);
-
- public Q_SLOTS:
- void
- propertyChanged (QStandardItem* property_item);
-
- Q_SIGNALS:
- void
- propertyChanged (const QStandardItem* property_item, const CloudComposerItem* parent_item_);
-
-
- private:
- CloudComposerItem* parent_item_;
-
- };
- }
-}
+namespace pcl {
+namespace cloud_composer {
+class CloudComposerItem;
+class PropertiesModel : public QStandardItemModel {
+ Q_OBJECT
+public:
+ /** \brief Constructor used for tool parameters */
+ PropertiesModel(QObject* parent = nullptr);
+ /** \brief Constructor used for item parameters */
+ PropertiesModel(CloudComposerItem* parent_item, QObject* parent = nullptr);
+ PropertiesModel(const PropertiesModel& to_copy);
-Q_DECLARE_METATYPE (pcl::cloud_composer::PropertiesModel);
-Q_DECLARE_METATYPE (pcl::cloud_composer::PropertiesModel*);
+ /** \brief Helper function for adding a new property */
+ void
+ addProperty(const QString& prop_name,
+ const QVariant& value,
+ const Qt::ItemFlags flags = Qt::ItemIsSelectable,
+ const QString& category = "");
+
+ /** \brief Helper function for adding a new property category */
+ void
+ addCategory(const QString& category_name);
+
+ /** \brief Helper function to get a property */
+ QVariant
+ getProperty(const QString& prop_name) const;
+
+ void
+ copyProperties(const PropertiesModel* to_copy);
+
+public Q_SLOTS:
+ void
+ propertyChanged(QStandardItem* property_item);
+
+Q_SIGNALS:
+ void
+ propertyChanged(const QStandardItem* property_item,
+ const CloudComposerItem* parent_item_);
+
+private:
+ CloudComposerItem* parent_item_;
+};
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(pcl::cloud_composer::PropertiesModel);
+Q_DECLARE_METATYPE(pcl::cloud_composer::PropertiesModel*);
/*
* Software License Agreement (BSD License)
*
- *
+ *
* Class to multiplex signal and slot connections. Qt 3 code from:
* http://doc.trolltech.com/qq/qq08-action-multiplexer.html.
* Converted to Qt 4 by a.somers@rathenau.nl.
- * Modified for use in cloud_composer by jpapon@gmail.com
- *
+ * Modified for use in cloud_composer by jpapon@gmail.com
+ *
* Point Cloud Library (PCL) - www.pointclouds.org
*
* All rights reserved.
#include <QObject>
#include <QPointer>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class SignalMultiplexer : public QObject {
+ Q_OBJECT
+
+public:
+ SignalMultiplexer(QObject* parent = nullptr);
+
+ /**
+ Use this connect function instead of QObject::connect() to connect
+ an actions activation signal to the receiving, multiplexed object.
+
+ @param sender the sending action or object
+ @param signal the signal in the sender object that is connected to
+ @param slot the slot in the receiving object that is set through @ref
+ setCurrentObject that the signal should be connected to.
+
+ @see connect(const char *signal, QObject *receiver, const char *slot)
+ @see disconnect(QObject *sender, const char *signal, const char *slot)
+ */
+ void
+ connect(QObject* sender, const char* signal, const char* slot);
+
+ /**
+ Disconnects a signal connection from a sending object to a multiplexed
+ receiving object.
+ @see connect(const char *signal, QObject *receiver, const char *slot)
+ */
+ bool
+ disconnect(QObject* sender, const char* signal, const char* slot);
+
+ /**
+ Use this connect function instead of QObject::connect() to connect
+ a multiplexed object's (status) signal to an action object's slot.
+
+ @param signal the signal in the multiplexed sender object that is set through
+ @ref setCurrentObject that the connection should be from
+ @param receiver the receiving action or object
+ @param slot the slot in the receiving object
+
+ @see connect(QObject *sender, const char *signal, const char *slot)
+ @see disconnect(const char *signal, QObject *receiver, const char *slot)
+ */
+ void
+ connect(const char* signal, QObject* receiver, const char* slot);
+
+ /**
+ Disconnects a signal from a multiplexed object to a receiving (action)
+ object.
+ @see connect(const char *signal, QObject *receiver, const char *slot)
+ */
+ bool
+ disconnect(const char* signal, QObject* receiver, const char* slot);
+
+ /**
+ @returns the object the connections are currently made with.
+ */
+ QObject*
+ currentObject() const
{
- class SignalMultiplexer : public QObject
- {
- Q_OBJECT
-
- public:
- SignalMultiplexer(QObject *parent = nullptr);
-
- /**
- Use this connect function instead of QObject::connect() to connect
- an actions activation signal to the receiving, multiplexed object.
-
- @param sender the sending action or object
- @param signal the signal in the sender object that is connected to
- @param slot the slot in the receiving object that is set through @ref
- setCurrentObject that the signal should be connected to.
-
- @see connect(const char *signal, QObject *receiver, const char *slot)
- @see disconnect(QObject *sender, const char *signal, const char *slot)
- */
- void
- connect (QObject *sender, const char *signal, const char *slot);
-
- /**
- Disconnects a signal connection from a sending object to a multiplexed
- receiving object.
- @see connect(const char *signal, QObject *receiver, const char *slot)
- */
- bool
- disconnect (QObject *sender, const char *signal, const char *slot);
-
- /**
- Use this connect function instead of QObject::connect() to connect
- a multiplexed object's (status) signal to an action object's slot.
-
- @param signal the signal in the multiplexed sender object that is set through
- @ref setCurrentObject that the connection should be from
- @param receiver the receiving action or object
- @param slot the slot in the receiving object
-
- @see connect(QObject *sender, const char *signal, const char *slot)
- @see disconnect(const char *signal, QObject *receiver, const char *slot)
- */
- void
- connect (const char *signal, QObject *receiver, const char *slot);
-
- /**
- Disconnects a signal from a multiplexed object to a receiving (action)
- object.
- @see connect(const char *signal, QObject *receiver, const char *slot)
- */
- bool
- disconnect (const char *signal, QObject *receiver, const char *slot);
-
- /**
- @returns the object the connections are currently made with.
- */
- QObject
- *currentObject () const { return object; }
-
- public Q_SLOTS:
- /**
- Sets the current object the signals that are managed by the
- SignalMultiplexer instance should be connected to. Any connections
- of these signals to the previous object will be disconnected.
- After the connections are hooked to the new object, the
- @ref currentObjectChanged signal will be emitted.
-
- @param newObject the new object that the signals should be connected to
- */
- void
- setCurrentObject (QObject *newObject);
-
- Q_SIGNALS:
- /**
- Emitted when a new object is set to receive the signals managed by
- this SignalMultiplexer instance.
- */
- void
- currentObjectChanged (QObject* newObject);
-
- private:
- struct Connection
- {
- QPointer<QObject> sender;
- QPointer<QObject> receiver;
- const char *signal;
- const char *slot;
- };
-
- void
- connect (const Connection &conn);
- void
- disconnect (const Connection &conn);
-
- QPointer<QObject> object;
- QList<Connection> connections;
- };
+ return object;
}
-}
+
+public Q_SLOTS:
+ /**
+ Sets the current object the signals that are managed by the
+ SignalMultiplexer instance should be connected to. Any connections
+ of these signals to the previous object will be disconnected.
+ After the connections are hooked to the new object, the
+ @ref currentObjectChanged signal will be emitted.
+
+ @param newObject the new object that the signals should be connected to
+ */
+ void
+ setCurrentObject(QObject* newObject);
+
+Q_SIGNALS:
+ /**
+ Emitted when a new object is set to receive the signals managed by
+ this SignalMultiplexer instance.
+ */
+ void
+ currentObjectChanged(QObject* newObject);
+
+private:
+ struct Connection {
+ QPointer<QObject> sender;
+ QPointer<QObject> receiver;
+ const char* signal;
+ const char* slot;
+ };
+
+ void
+ connect(const Connection& conn);
+ void
+ disconnect(const Connection& conn);
+
+ QPointer<QObject> object;
+ QList<Connection> connections;
+};
+} // namespace cloud_composer
+} // namespace pcl
#include <QDebug>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+
+class AbstractTool : public QObject {
+ Q_OBJECT
+public:
+ AbstractTool(PropertiesModel* parameter_model, QObject* parent);
+
+ ~AbstractTool() { qDebug() << "Tool Destructed"; }
+
+ /** \brief Function called which does work in plugin
+ * \param data input_data from the model - const for good reason
+ * Returned list will become the output, replacing input_data in the model - you must
+ * deep copy the input_data, since undo works by switching back and forth
+ */
+ virtual QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) = 0;
+
+ virtual CloudCommand*
+ createCommand(QList<const CloudComposerItem*> input_data) = 0;
+
+ QString
+ getActionText() const
+ {
+ return action_text_;
+ }
+
+ void
+ setActionText(const QString& text)
+ {
+ action_text_ = text;
+ }
+
+ virtual QString
+ getToolName() const = 0;
+
+protected:
+ PropertiesModel* parameter_model_;
+
+private:
+ QString action_text_;
+};
+
+class ModifyItemTool : public AbstractTool {
+ Q_OBJECT
+public:
+ ModifyItemTool(PropertiesModel* parameter_model, QObject* parent)
+ : AbstractTool(parameter_model, parent)
+ {}
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
+
+ inline CloudCommand*
+ createCommand(QList<const CloudComposerItem*> input_data) override
{
-
-
- class AbstractTool : public QObject
- {
- Q_OBJECT
- public:
-
- AbstractTool (PropertiesModel* parameter_model, QObject* parent);
-
- ~AbstractTool () { qDebug() << "Tool Destructed"; }
-
- /** \brief Function called which does work in plugin
- * \param data input_data from the model - const for good reason
- * Returned list will become the output, replacing input_data in the model - you must deep copy
- * the input_data, since undo works by switching back and forth
- */
- virtual QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) = 0;
-
- virtual CloudCommand*
- createCommand (QList <const CloudComposerItem*> input_data) = 0;
-
- QString
- getActionText () const {return action_text_;}
-
- void
- setActionText (const QString& text) { action_text_ = text; }
-
- virtual QString
- getToolName () const = 0;
-
- protected:
-
- PropertiesModel* parameter_model_;
-
- private:
- QString action_text_;
-
- };
-
- class ModifyItemTool : public AbstractTool
- {
- Q_OBJECT
- public:
- ModifyItemTool (PropertiesModel* parameter_model, QObject* parent)
- : AbstractTool (parameter_model, parent)
- {}
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
-
- inline CloudCommand*
- createCommand (QList <const CloudComposerItem*> input_data) override
- {
- return new ModifyItemCommand (input_data);
- }
-
- inline QString
- getToolName () const override { return "ModifyItemTool";}
-
- };
-
- class NewItemTool : public AbstractTool
- {
- Q_OBJECT
- public:
- NewItemTool (PropertiesModel* parameter_model, QObject* parent)
- : AbstractTool (parameter_model, parent)
- {}
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
-
- inline CloudCommand*
- createCommand (QList <const CloudComposerItem*> input_data) override
- {
- return new NewItemCloudCommand (input_data);
- }
-
- inline QString
- getToolName () const override { return "NewItemTool";}
-
- };
-
- class SplitItemTool : public AbstractTool
- {
- Q_OBJECT
- public:
- SplitItemTool (PropertiesModel* parameter_model, QObject* parent)
- : AbstractTool (parameter_model, parent)
- {}
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
-
- inline CloudCommand*
- createCommand (QList <const CloudComposerItem*> input_data) override
- {
- return new SplitCloudCommand (input_data);
- }
-
- inline QString
- getToolName () const override { return "SplitItemTool";}
-
- };
-
- class MergeCloudTool : public AbstractTool
- {
- Q_OBJECT
- public:
- MergeCloudTool (PropertiesModel* parameter_model, QObject* parent)
- : AbstractTool (parameter_model, parent)
- {}
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
-
- inline CloudCommand*
- createCommand (QList <const CloudComposerItem*> input_data) override
- {
- return new MergeCloudCommand (input_data);
- }
-
- inline QString
- getToolName () const override { return "MergeCloudTool";}
-
- };
+ return new ModifyItemCommand(input_data);
+ }
+ inline QString
+ getToolName() const override
+ {
+ return "ModifyItemTool";
}
-}
+};
+
+class NewItemTool : public AbstractTool {
+ Q_OBJECT
+public:
+ NewItemTool(PropertiesModel* parameter_model, QObject* parent)
+ : AbstractTool(parameter_model, parent)
+ {}
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
+
+ inline CloudCommand*
+ createCommand(QList<const CloudComposerItem*> input_data) override
+ {
+ return new NewItemCloudCommand(input_data);
+ }
+
+ inline QString
+ getToolName() const override
+ {
+ return "NewItemTool";
+ }
+};
+
+class SplitItemTool : public AbstractTool {
+ Q_OBJECT
+public:
+ SplitItemTool(PropertiesModel* parameter_model, QObject* parent)
+ : AbstractTool(parameter_model, parent)
+ {}
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
+
+ inline CloudCommand*
+ createCommand(QList<const CloudComposerItem*> input_data) override
+ {
+ return new SplitCloudCommand(input_data);
+ }
+
+ inline QString
+ getToolName() const override
+ {
+ return "SplitItemTool";
+ }
+};
+
+class MergeCloudTool : public AbstractTool {
+ Q_OBJECT
+public:
+ MergeCloudTool(PropertiesModel* parameter_model, QObject* parent)
+ : AbstractTool(parameter_model, parent)
+ {}
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
+
+ inline CloudCommand*
+ createCommand(QList<const CloudComposerItem*> input_data) override
+ {
+ return new MergeCloudCommand(input_data);
+ }
+
+ inline QString
+ getToolName() const override
+ {
+ return "MergeCloudTool";
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
class QAction;
-namespace pcl
-{
- namespace cloud_composer
- {
-
-
- class AbstractTool;
- class AbstractCommand;
- class PropertiesModel;
-
- class ToolFactory
- {
- public:
- virtual AbstractTool*
- createTool (PropertiesModel* parameter_model = nullptr, QObject* parent = nullptr) = 0;
-
- virtual PropertiesModel*
- createToolParameterModel (QObject* parent) = 0;
-
- virtual QString
- getPluginName () const = 0;
-
- virtual QString
- getToolGroupName () const = 0;
-
- virtual QString
- getIconName () const = 0;
-
- /** \brief Reimplement this function to return the proper number if tool requires more than one input item */
- inline virtual int
- getNumInputItems () const
- {
- return 1;
- }
-
- /** \brief Returns a list of allowed input item types. Implement in tools so GUI can prevent impossible actions */
- virtual CloudComposerItem::ItemType
- getInputItemType () const = 0;
-
- /** \brief Returns a list of required input children. Implement in tools so GUI can prevent impossible actions */
- virtual QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const = 0;
-
- };
+namespace pcl {
+namespace cloud_composer {
+
+class AbstractTool;
+class AbstractCommand;
+class PropertiesModel;
+
+class ToolFactory {
+public:
+ virtual AbstractTool*
+ createTool(PropertiesModel* parameter_model = nullptr, QObject* parent = nullptr) = 0;
+
+ virtual PropertiesModel*
+ createToolParameterModel(QObject* parent) = 0;
+
+ virtual QString
+ getPluginName() const = 0;
+
+ virtual QString
+ getToolGroupName() const = 0;
+ virtual QString
+ getIconName() const = 0;
+
+ /** \brief Reimplement this function to return the proper number if tool requires more
+ * than one input item */
+ inline virtual int
+ getNumInputItems() const
+ {
+ return 1;
}
-}
-Q_DECLARE_METATYPE (pcl::cloud_composer::ToolFactory*);
+ /** \brief Returns a list of allowed input item types. Implement in tools so GUI can
+ * prevent impossible actions */
+ virtual CloudComposerItem::ItemType
+ getInputItemType() const = 0;
+
+ /** \brief Returns a list of required input children. Implement in tools so GUI can
+ * prevent impossible actions */
+ virtual QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const = 0;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(pcl::cloud_composer::ToolFactory*);
-Q_DECLARE_INTERFACE(pcl::cloud_composer::ToolFactory,
- "cloud_composer.ToolFactory/1.0")
+Q_DECLARE_INTERFACE(pcl::cloud_composer::ToolFactory, "cloud_composer.ToolFactory/1.0")
class QItemSelectionModel;
class QTreeView;
-enum TOOLBOX_ROLES
-{
+enum TOOLBOX_ROLES {
FACTORY = Qt::UserRole,
PARAMETER_MODEL,
ALLOWED_INPUT_ITEM_TYPES,
};
class QTreeView;
-namespace pcl
-{
- namespace cloud_composer
- {
-
- class CloudCommand;
- class AbstractTool;
- class ToolFactory;
- class ProjectModel;
-
- class ToolBoxModel : public QStandardItemModel
- {
- Q_OBJECT
-
- public:
- ToolBoxModel (QTreeView* tool_view = nullptr, QTreeView* parameter_view = nullptr, QObject *parent = nullptr);
- ToolBoxModel (const ToolBoxModel& to_copy);
-
- void
- addTool (ToolFactory* tool_factory);
-
- void
- setSelectionModel (QItemSelectionModel* selection_model);
-
- /** \brief Enables/Disables Tools based on currently selected items from model */
- void
- updateEnabledTools (const QItemSelection& current_selection);
-
- void
- enableAllTools ();
-
- public Q_SLOTS:
- void
- activeProjectChanged (ProjectModel* new_model, ProjectModel* previous_model);
-
- void
- selectedToolChanged (const QModelIndex & current, const QModelIndex & previous);
-
- void
- toolAction ();
-
- /** \brief This slot is called when the selection in cloud browser changes. Updates enabling of tools */
- void
- selectedItemChanged ( const QItemSelection & selected, const QItemSelection & deselected );
-
- /** \brief This slot is called whenever the current project model emits layoutChanged, and calls updateEnabledTools */
- void
- modelChanged ();
- Q_SIGNALS:
- void
- enqueueToolAction (AbstractTool* tool);
-
- private:
- QStandardItem*
- addToolGroup (const QString& tool_group_name);
-
- QTreeView* tool_view_;
- QTreeView* parameter_view_;
- QItemSelectionModel* selection_model_;
- QSet <QStandardItem*> tool_items;
-
- ProjectModel* project_model_;
- };
- }
-}
-
-Q_DECLARE_METATYPE (pcl::cloud_composer::ToolBoxModel);
-Q_DECLARE_METATYPE (QStandardItemModel*);
+namespace pcl {
+namespace cloud_composer {
+
+class CloudCommand;
+class AbstractTool;
+class ToolFactory;
+class ProjectModel;
+
+class ToolBoxModel : public QStandardItemModel {
+ Q_OBJECT
+
+public:
+ ToolBoxModel(QTreeView* tool_view = nullptr,
+ QTreeView* parameter_view = nullptr,
+ QObject* parent = nullptr);
+ ToolBoxModel(const ToolBoxModel& to_copy);
+
+ void
+ addTool(ToolFactory* tool_factory);
+
+ void
+ setSelectionModel(QItemSelectionModel* selection_model);
+
+ /** \brief Enables/Disables Tools based on currently selected items from model */
+ void
+ updateEnabledTools(const QItemSelection& current_selection);
+
+ void
+ enableAllTools();
+
+public Q_SLOTS:
+ void
+ activeProjectChanged(ProjectModel* new_model, ProjectModel* previous_model);
+
+ void
+ selectedToolChanged(const QModelIndex& current, const QModelIndex& previous);
+
+ void
+ toolAction();
+
+ /** \brief This slot is called when the selection in cloud browser changes. Updates
+ * enabling of tools */
+ void
+ selectedItemChanged(const QItemSelection& selected, const QItemSelection& deselected);
+
+ /** \brief This slot is called whenever the current project model emits layoutChanged,
+ * and calls updateEnabledTools */
+ void
+ modelChanged();
+Q_SIGNALS:
+ void
+ enqueueToolAction(AbstractTool* tool);
+
+private:
+ QStandardItem*
+ addToolGroup(const QString& tool_group_name);
+
+ QTreeView* tool_view_;
+ QTreeView* parameter_view_;
+ QItemSelectionModel* selection_model_;
+ QSet<QStandardItem*> tool_items;
+
+ ProjectModel* project_model_;
+};
+} // namespace cloud_composer
+} // namespace pcl
+
+Q_DECLARE_METATYPE(pcl::cloud_composer::ToolBoxModel);
+Q_DECLARE_METATYPE(QStandardItemModel*);
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class EuclideanClusteringTool : public SplitItemTool {
+ Q_OBJECT
+public:
+ EuclideanClusteringTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
+ {
+ return "Euclidean Clustering Tool";
+ }
+};
+
+class EuclideanClusteringToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ SplitItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new EuclideanClusteringTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
{
- class EuclideanClusteringTool : public SplitItemTool
- {
- Q_OBJECT
- public:
- EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Euclidean Clustering Tool";}
- };
+ return "Euclidean Clustering";
+ }
-
- class EuclideanClusteringToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- SplitItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new EuclideanClusteringTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Euclidean Clustering";}
-
- inline QString
- getToolGroupName () const override { return "Segmentation";}
-
- inline QString
- getIconName () const override { return ":/euclidean_clustering.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- return QList <CloudComposerItem::ItemType> ();
- }
- };
+ inline QString
+ getToolGroupName() const override
+ {
+ return "Segmentation";
+ }
+ inline QString
+ getIconName() const override
+ {
+ return ":/euclidean_clustering.png";
+ }
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ return QList<CloudComposerItem::ItemType>();
}
-}
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+
+class FPFHEstimationTool : public NewItemTool {
+ Q_OBJECT
+public:
+ FPFHEstimationTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
{
-
- class FPFHEstimationTool : public NewItemTool
- {
- Q_OBJECT
- public:
- FPFHEstimationTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "FPFH Estimation Tool";}
- };
+ return "FPFH Estimation Tool";
+ }
+};
-
- class FPFHEstimationToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- NewItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new FPFHEstimationTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "FPFH Estimation";}
-
- QString
- getToolGroupName () const override { return "Feature Estimation";}
-
- QString
- getIconName () const override { return ":/fpfh_estimation.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- QList <CloudComposerItem::ItemType> input_types;
- return (input_types << CloudComposerItem::NORMALS_ITEM);
- }
- };
+class FPFHEstimationToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ NewItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new FPFHEstimationTool(parameter_model, parent);
+ }
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+ inline QString
+ getPluginName() const override
+ {
+ return "FPFH Estimation";
+ }
+ QString
+ getToolGroupName() const override
+ {
+ return "Feature Estimation";
}
-}
+
+ QString
+ getIconName() const override
+ {
+ return ":/fpfh_estimation.png";
+ }
+
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ QList<CloudComposerItem::ItemType> input_types;
+ return (input_types << CloudComposerItem::NORMALS_ITEM);
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#ifndef IMPL_ORGANIZED_SEGMENTATION_HPP_
#define IMPL_ORGANIZED_SEGMENTATION_HPP_
-#include <pcl/apps/cloud_composer/tools/organized_segmentation.h>
#include <pcl/apps/cloud_composer/impl/cloud_item.hpp>
#include <pcl/apps/cloud_composer/items/normals_item.h>
-#include <pcl/memory.h> // for pcl::make_shared
-#include <pcl/point_cloud.h>
-
-#include <pcl/segmentation/organized_multi_plane_segmentation.h>
-#include <pcl/segmentation/plane_coefficient_comparator.h>
-#include <pcl/segmentation/euclidean_plane_coefficient_comparator.h>
-#include <pcl/segmentation/rgb_plane_coefficient_comparator.h>
+#include <pcl/apps/cloud_composer/tools/organized_segmentation.h>
+#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/edge_aware_plane_comparator.h>
#include <pcl/segmentation/euclidean_cluster_comparator.h>
+#include <pcl/segmentation/euclidean_plane_coefficient_comparator.h>
#include <pcl/segmentation/organized_connected_component_segmentation.h>
+#include <pcl/segmentation/organized_multi_plane_segmentation.h>
+#include <pcl/segmentation/plane_coefficient_comparator.h>
+#include <pcl/segmentation/rgb_plane_coefficient_comparator.h>
+#include <pcl/memory.h> // for pcl::make_shared
+#include <pcl/point_cloud.h>
-
-template <typename PointT> QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction (const QList <const CloudComposerItem*>& input_data)
+template <typename PointT>
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction(
+ const QList<const CloudComposerItem*>& input_data)
{
- QList <CloudComposerItem*> output;
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- if ( ! variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)";
+ QList<CloudComposerItem*> output;
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ if (!variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ qWarning() << "Attempted to cast to template type which does not exist in this "
+ "item! (input list)";
return output;
}
- typename PointCloud <PointT>::Ptr input_cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
- if ( ! input_cloud->isOrganized ())
- {
- qCritical () << "Organized Segmentation requires an organized cloud!";
+ typename PointCloud<PointT>::Ptr input_cloud =
+ variant.value<typename PointCloud<PointT>::Ptr>();
+ if (!input_cloud->isOrganized()) {
+ qCritical() << "Organized Segmentation requires an organized cloud!";
return output;
}
}
- int min_inliers = parameter_model_->getProperty ("Min Inliers").toInt ();
- int min_plane_size = parameter_model_->getProperty ("Min Plane Size").toInt ();
- double angular_threshold = parameter_model_->getProperty ("Angular Threshold").toDouble ();
- double distance_threshold = parameter_model_->getProperty ("Distance Threshold").toDouble ();
- double cluster_distance_threshold = parameter_model_->getProperty ("Cluster Dist. Thresh.").toDouble ();
- int min_cluster_size = parameter_model_->getProperty ("Min Cluster Size").toInt ();
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- QList <CloudComposerItem*> normals_list = input_item->getChildren (CloudComposerItem::NORMALS_ITEM);
- //Get the normals cloud, we just use the first normals that were found if there are more than one
- pcl::PointCloud<pcl::Normal>::ConstPtr input_normals = normals_list.value(0)->data(ItemDataRole::CLOUD_TEMPLATED).value <pcl::PointCloud<pcl::Normal>::ConstPtr> ();
-
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- typename PointCloud <PointT>::Ptr input_cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
+ int min_inliers = parameter_model_->getProperty("Min Inliers").toInt();
+ int min_plane_size = parameter_model_->getProperty("Min Plane Size").toInt();
+ double angular_threshold =
+ parameter_model_->getProperty("Angular Threshold").toDouble();
+ double distance_threshold =
+ parameter_model_->getProperty("Distance Threshold").toDouble();
+ double cluster_distance_threshold =
+ parameter_model_->getProperty("Cluster Dist. Thresh.").toDouble();
+ int min_cluster_size = parameter_model_->getProperty("Min Cluster Size").toInt();
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ QList<CloudComposerItem*> normals_list =
+ input_item->getChildren(CloudComposerItem::NORMALS_ITEM);
+ // Get the normals cloud, we just use the first normals that were found if there are
+ // more than one
+ pcl::PointCloud<pcl::Normal>::ConstPtr input_normals =
+ normals_list.value(0)
+ ->data(ItemDataRole::CLOUD_TEMPLATED)
+ .value<pcl::PointCloud<pcl::Normal>::ConstPtr>();
+
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ typename PointCloud<PointT>::Ptr input_cloud =
+ variant.value<typename PointCloud<PointT>::Ptr>();
pcl::OrganizedMultiPlaneSegmentation<PointT, pcl::Normal, pcl::Label> mps;
- mps.setMinInliers (min_inliers);
- mps.setAngularThreshold (pcl::deg2rad (angular_threshold)); // convert to radians
- mps.setDistanceThreshold (distance_threshold);
- mps.setInputNormals (input_normals);
- mps.setInputCloud (input_cloud);
- std::vector<pcl::PlanarRegion<PointT>, Eigen::aligned_allocator<pcl::PlanarRegion<PointT> > > regions;
+ mps.setMinInliers(min_inliers);
+ mps.setAngularThreshold(pcl::deg2rad(angular_threshold)); // convert to radians
+ mps.setDistanceThreshold(distance_threshold);
+ mps.setInputNormals(input_normals);
+ mps.setInputCloud(input_cloud);
+ std::vector<pcl::PlanarRegion<PointT>,
+ Eigen::aligned_allocator<pcl::PlanarRegion<PointT>>>
+ regions;
std::vector<pcl::ModelCoefficients> model_coefficients;
std::vector<pcl::PointIndices> inlier_indices;
- pcl::PointCloud<pcl::Label>::Ptr labels (new pcl::PointCloud<pcl::Label>);
+ pcl::PointCloud<pcl::Label>::Ptr labels(new pcl::PointCloud<pcl::Label>);
std::vector<pcl::PointIndices> label_indices;
std::vector<pcl::PointIndices> boundary_indices;
- mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
-
- auto plane_labels = pcl::make_shared<std::set<std::uint32_t> > ();
- for (std::size_t i = 0; i < label_indices.size (); ++i)
- if (label_indices[i].indices.size () > (std::size_t) min_plane_size)
- plane_labels->insert (i);
+ mps.segmentAndRefine(regions,
+ model_coefficients,
+ inlier_indices,
+ labels,
+ label_indices,
+ boundary_indices);
+
+ auto plane_labels = pcl::make_shared<std::set<std::uint32_t>>();
+ for (std::size_t i = 0; i < label_indices.size(); ++i)
+ if (label_indices[i].indices.size() > (std::size_t)min_plane_size)
+ plane_labels->insert(i);
typename PointCloud<PointT>::CloudVectorType clusters;
- typename EuclideanClusterComparator<PointT, pcl::Label>::Ptr euclidean_cluster_comparator(new EuclideanClusterComparator<PointT, pcl::Label>);
- euclidean_cluster_comparator->setInputCloud (input_cloud);
- euclidean_cluster_comparator->setLabels (labels);
- euclidean_cluster_comparator->setExcludeLabels (plane_labels);
- euclidean_cluster_comparator->setDistanceThreshold (cluster_distance_threshold, false);
+ typename EuclideanClusterComparator<PointT, pcl::Label>::Ptr
+ euclidean_cluster_comparator(
+ new EuclideanClusterComparator<PointT, pcl::Label>);
+ euclidean_cluster_comparator->setInputCloud(input_cloud);
+ euclidean_cluster_comparator->setLabels(labels);
+ euclidean_cluster_comparator->setExcludeLabels(plane_labels);
+ euclidean_cluster_comparator->setDistanceThreshold(cluster_distance_threshold,
+ false);
pcl::PointCloud<pcl::Label> euclidean_labels;
std::vector<pcl::PointIndices> euclidean_label_indices;
- pcl::OrganizedConnectedComponentSegmentation<PointT,pcl::Label> euclidean_segmentation (euclidean_cluster_comparator);
- euclidean_segmentation.setInputCloud (input_cloud);
- euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);
-
- pcl::IndicesPtr extracted_indices (new pcl::Indices ());
- for (std::size_t i = 0; i < euclidean_label_indices.size (); i++)
- {
- if (euclidean_label_indices[i].indices.size () >= (std::size_t) min_cluster_size)
- {
- typename PointCloud<PointT>::Ptr cluster (new PointCloud<PointT>);
- pcl::copyPointCloud (*input_cloud,euclidean_label_indices[i].indices,*cluster);
- qDebug () << "Found cluster with size " << cluster->width;
- QString name = input_item->text () + tr ("- Clstr %1").arg (i);
- CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(name,cluster);
- output.append (new_cloud_item);
- extracted_indices->insert (extracted_indices->end (), euclidean_label_indices[i].indices.begin (), euclidean_label_indices[i].indices.end ());
+ pcl::OrganizedConnectedComponentSegmentation<PointT, pcl::Label>
+ euclidean_segmentation(euclidean_cluster_comparator);
+ euclidean_segmentation.setInputCloud(input_cloud);
+ euclidean_segmentation.segment(euclidean_labels, euclidean_label_indices);
+
+ pcl::IndicesPtr extracted_indices(new pcl::Indices());
+ for (std::size_t i = 0; i < euclidean_label_indices.size(); i++) {
+ if (euclidean_label_indices[i].indices.size() >= (std::size_t)min_cluster_size) {
+ typename PointCloud<PointT>::Ptr cluster(new PointCloud<PointT>);
+ pcl::copyPointCloud(*input_cloud, euclidean_label_indices[i].indices, *cluster);
+ qDebug() << "Found cluster with size " << cluster->width;
+ QString name = input_item->text() + tr("- Clstr %1").arg(i);
+ CloudItem* new_cloud_item =
+ CloudItem::createCloudItemFromTemplate<PointT>(name, cluster);
+ output.append(new_cloud_item);
+ extracted_indices->insert(extracted_indices->end(),
+ euclidean_label_indices[i].indices.begin(),
+ euclidean_label_indices[i].indices.end());
}
}
- for (std::size_t i = 0; i < label_indices.size (); i++)
- {
- if (label_indices[i].indices.size () >= (std::size_t) min_plane_size)
- {
- typename PointCloud<PointT>::Ptr plane (new PointCloud<PointT>);
- pcl::copyPointCloud (*input_cloud,label_indices[i].indices,*plane);
- qDebug () << "Found plane with size " << plane->width;
- QString name = input_item->text () + tr ("- Plane %1").arg (i);
- CloudItem* new_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(name,plane);
- output.append (new_cloud_item);
- extracted_indices->insert (extracted_indices->end (), label_indices[i].indices.begin (), label_indices[i].indices.end ());
-
+ for (std::size_t i = 0; i < label_indices.size(); i++) {
+ if (label_indices[i].indices.size() >= (std::size_t)min_plane_size) {
+ typename PointCloud<PointT>::Ptr plane(new PointCloud<PointT>);
+ pcl::copyPointCloud(*input_cloud, label_indices[i].indices, *plane);
+ qDebug() << "Found plane with size " << plane->width;
+ QString name = input_item->text() + tr("- Plane %1").arg(i);
+ CloudItem* new_cloud_item =
+ CloudItem::createCloudItemFromTemplate<PointT>(name, plane);
+ output.append(new_cloud_item);
+ extracted_indices->insert(extracted_indices->end(),
+ label_indices[i].indices.begin(),
+ label_indices[i].indices.end());
}
}
- typename PointCloud<PointT>::Ptr leftovers (new PointCloud<PointT>);
- if (extracted_indices->empty ())
- pcl::copyPointCloud (*input_cloud,*leftovers);
- else
- {
+ typename PointCloud<PointT>::Ptr leftovers(new PointCloud<PointT>);
+ if (extracted_indices->empty())
+ pcl::copyPointCloud(*input_cloud, *leftovers);
+ else {
pcl::ExtractIndices<PointT> filter;
- filter.setInputCloud (input_cloud);
- filter.setIndices (extracted_indices);
- filter.setNegative (true);
- filter.filter (*leftovers);
+ filter.setInputCloud(input_cloud);
+ filter.setIndices(extracted_indices);
+ filter.setNegative(true);
+ filter.filter(*leftovers);
}
- CloudItem* leftover_cloud_item = CloudItem::createCloudItemFromTemplate<PointT>(input_item->text(),leftovers);
- output.append (leftover_cloud_item);
+ CloudItem* leftover_cloud_item =
+ CloudItem::createCloudItemFromTemplate<PointT>(input_item->text(), leftovers);
+ output.append(leftover_cloud_item);
}
-
-
-
return output;
-
}
+#define PCL_INSTANTIATE_performTemplatedAction(T) \
+ template void \
+ pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction<T>( \
+ QList<const CloudComposerItem*>);
-#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::OrganizedSegmentationTool::performTemplatedAction<T> (QList <const CloudComposerItem*>);
-
-
-
-#endif //IMPL_TRANSFORM_CLOUDS_HPP_
+#endif // IMPL_TRANSFORM_CLOUDS_HPP_
/*
-* Software License Agreement (BSD License)
-*
-* Point Cloud Library (PCL) - www.pointclouds.org
-* Copyright (c) 2012, Jeremie Papon.
-*
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of Willow Garage, Inc. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*
-*/
+ * Software License Agreement (BSD License)
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2012, Jeremie Papon.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
#ifndef IMPL_SUPERVOXELS_HPP_
#define IMPL_SUPERVOXELS_HPP_
-#include <pcl/apps/cloud_composer/tools/supervoxels.h>
#include <pcl/apps/cloud_composer/impl/cloud_item.hpp>
#include <pcl/apps/cloud_composer/items/normals_item.h>
+#include <pcl/apps/cloud_composer/tools/supervoxels.h>
+#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/memory.h>
#include <pcl/point_cloud.h>
-#include <pcl/segmentation/supervoxel_clustering.h>
-
-template <typename PointT> QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::SupervoxelsTool::performTemplatedAction (const QList <const CloudComposerItem*>& input_data)
+template <typename PointT>
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::SupervoxelsTool::performTemplatedAction(
+ const QList<const CloudComposerItem*>& input_data)
{
- QList <CloudComposerItem*> output;
-
- foreach (const CloudComposerItem* input_item, input_data)
- {
- // if ( !input_item->isSanitized () )
- // {
- // qCritical () << "SupervoxelsTool requires sanitized input!";
- // return output;
- // }
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- if ( ! variant.canConvert <typename PointCloud<PointT>::Ptr> () )
- {
- qWarning () << "Attempted to cast to template type which does not exist in this item! (input list)";
+ QList<CloudComposerItem*> output;
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ // if ( !input_item->isSanitized () )
+ // {
+ // qCritical () << "SupervoxelsTool requires sanitized input!";
+ // return output;
+ // }
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ if (!variant.canConvert<typename PointCloud<PointT>::Ptr>()) {
+ qWarning() << "Attempted to cast to template type which does not exist in this "
+ "item! (input list)";
return output;
}
- typename PointCloud <PointT>::Ptr input_cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
- //TODO: Check if Voxelized
-
-}
-
+ typename PointCloud<PointT>::Ptr input_cloud =
+ variant.value<typename PointCloud<PointT>::Ptr>();
+ // TODO: Check if Voxelized
+ }
+
+ foreach (const CloudComposerItem* input_item, input_data) {
+ QVariant variant = input_item->data(ItemDataRole::CLOUD_TEMPLATED);
+ typename PointCloud<PointT>::Ptr input_cloud =
+ variant.value<typename PointCloud<PointT>::Ptr>();
+
+ float resolution = parameter_model_->getProperty("Resolution").toFloat();
+ qDebug() << "Octree resolution = " << resolution;
+ float seed_resolution = parameter_model_->getProperty("Seed Resolution").toFloat();
+ qDebug() << "Seed resolution = " << seed_resolution;
+
+ float rgb_weight = parameter_model_->getProperty("RGB Weight").toFloat();
+ float normal_weight = parameter_model_->getProperty("Normals Weight").toFloat();
+ float spatial_weight = parameter_model_->getProperty("Spatial Weight").toFloat();
+
+ pcl::SupervoxelClustering<PointT> super(resolution, seed_resolution);
+ super.setInputCloud(input_cloud);
+ super.setColorImportance(rgb_weight);
+ super.setSpatialImportance(spatial_weight);
+ super.setNormalImportance(normal_weight);
+ std::map<std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;
+ super.extract(supervoxel_clusters);
+
+ std::map<std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr>
+ refined_supervoxel_clusters;
+ super.refineSupervoxels(3, refined_supervoxel_clusters);
- foreach (const CloudComposerItem* input_item, input_data)
- {
- QVariant variant = input_item->data (ItemDataRole::CLOUD_TEMPLATED);
- typename PointCloud <PointT>::Ptr input_cloud = variant.value <typename PointCloud<PointT>::Ptr> ();
-
- float resolution = parameter_model_->getProperty("Resolution").toFloat ();
- qDebug () << "Octree resolution = "<<resolution;
- float seed_resolution = parameter_model_->getProperty("Seed Resolution").toFloat ();
- qDebug () << "Seed resolution = "<<seed_resolution;
-
- float rgb_weight = parameter_model_->getProperty("RGB Weight").toFloat ();
- float normal_weight = parameter_model_->getProperty("Normals Weight").toFloat ();
- float spatial_weight = parameter_model_->getProperty("Spatial Weight").toFloat ();
-
-
- pcl::SupervoxelClustering<PointT> super (resolution, seed_resolution);
- super.setInputCloud (input_cloud);
- super.setColorImportance (rgb_weight);
- super.setSpatialImportance (spatial_weight);
- super.setNormalImportance (normal_weight);
- std::map <std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr > supervoxel_clusters;
- super.extract (supervoxel_clusters);
-
- std::map <std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr > refined_supervoxel_clusters;
- super.refineSupervoxels (3, refined_supervoxel_clusters);
-
auto label_segments = super.getLabeledVoxelCloud();
auto color_segments = pcl::make_shared<pcl::PointCloud<PointXYZRGBA>>();
pcl::copyPointCloud(*label_segments, *color_segments);
for (size_t i = 0; i < label_segments->size(); ++i)
- color_segments->at(i).rgba = GlasbeyLUT::at(label_segments->at(i).label % GlasbeyLUT::size()).rgba;
- CloudItem* cloud_item_out = CloudItem::createCloudItemFromTemplate<PointXYZRGBA>(input_item->text(), color_segments);
-
- output.append (cloud_item_out);
-
+ color_segments->at(i).rgba =
+ GlasbeyLUT::at(label_segments->at(i).label % GlasbeyLUT::size()).rgba;
+ CloudItem* cloud_item_out = CloudItem::createCloudItemFromTemplate<PointXYZRGBA>(
+ input_item->text(), color_segments);
+
+ output.append(cloud_item_out);
}
-
-
-
-
+
return output;
-
}
+#define PCL_INSTANTIATE_performTemplatedAction(T) \
+ template void pcl::cloud_composer::SupervoxelsTool::performTemplatedAction<T>( \
+ QList<const CloudComposerItem*>);
-
-
-#define PCL_INSTANTIATE_performTemplatedAction(T) template void pcl::cloud_composer::SupervoxelsTool::performTemplatedAction<T> (QList <const CloudComposerItem*>);
-
-
-
-#endif //IMPL_SUPERVOXELS_HPP_
+#endif // IMPL_SUPERVOXELS_HPP_
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class NormalEstimationTool : public NewItemTool {
+ Q_OBJECT
+public:
+ NormalEstimationTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
+ {
+ return "Normal Estimation Tool";
+ }
+};
+
+class NormalEstimationToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ NewItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new NormalEstimationTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
{
- class NormalEstimationTool : public NewItemTool
- {
- Q_OBJECT
- public:
- NormalEstimationTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Normal Estimation Tool";}
- };
+ return "Normal Estimation";
+ }
-
- class NormalEstimationToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- NewItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new NormalEstimationTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Normal Estimation";}
-
- QString
- getToolGroupName () const override { return "Feature Estimation";}
-
- QString
- getIconName () const override { return ":/normal_estimation.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- return QList <CloudComposerItem::ItemType> ();
- }
- };
+ QString
+ getToolGroupName() const override
+ {
+ return "Feature Estimation";
+ }
+ QString
+ getIconName() const override
+ {
+ return ":/normal_estimation.png";
+ }
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ return QList<CloudComposerItem::ItemType>();
}
-}
+};
+
+} // namespace cloud_composer
+} // namespace pcl
- /*
- * Software License Agreement (BSD License)
- *
- * Point Cloud Library (PCL) - www.pointclouds.org
- * Copyright (c) 2012, Jeremie Papon.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Willow Garage, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2012, Jeremie Papon.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
#pragma once
-
- #include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
- #include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-
-
- namespace pcl
- {
- namespace cloud_composer
- {
- class OrganizedSegmentationTool : public SplitItemTool
- {
- Q_OBJECT
- public:
- OrganizedSegmentationTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- template <typename PointT> QList <CloudComposerItem*>
- performTemplatedAction (const QList <const CloudComposerItem*>& input_data);
-
- inline QString
- getToolName () const override { return "Organized Segmentation Tool";}
- };
-
-
- class OrganizedSegmentationToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- SplitItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new OrganizedSegmentationTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Organized Segmentation";}
-
- inline QString
- getToolGroupName () const override { return "Segmentation";}
-
- inline QString
- getIconName () const override { return ":/organized_segmentation.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- QList <CloudComposerItem::ItemType> input_types;
- return (input_types << CloudComposerItem::NORMALS_ITEM);
- }
- };
-
-
-
- }
- }
+
+#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
+#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
+
+namespace pcl {
+namespace cloud_composer {
+class OrganizedSegmentationTool : public SplitItemTool {
+ Q_OBJECT
+public:
+ OrganizedSegmentationTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ template <typename PointT>
+ QList<CloudComposerItem*>
+ performTemplatedAction(const QList<const CloudComposerItem*>& input_data);
+
+ inline QString
+ getToolName() const override
+ {
+ return "Organized Segmentation Tool";
+ }
+};
+
+class OrganizedSegmentationToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ SplitItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new OrganizedSegmentationTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
+ {
+ return "Organized Segmentation";
+ }
+
+ inline QString
+ getToolGroupName() const override
+ {
+ return "Segmentation";
+ }
+
+ inline QString
+ getIconName() const override
+ {
+ return ":/organized_segmentation.png";
+ }
+
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ QList<CloudComposerItem::ItemType> input_types;
+ return (input_types << CloudComposerItem::NORMALS_ITEM);
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class SanitizeCloudTool : public ModifyItemTool {
+ Q_OBJECT
+public:
+ SanitizeCloudTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
+ {
+ return "Sanitize Cloud Tool";
+ }
+};
+
+class SanitizeCloudToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ ModifyItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new SanitizeCloudTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
+ {
+ return "Sanitize Cloud";
+ }
+
+ QString
+ getToolGroupName() const override
+ {
+ return "Filters";
+ }
+
+ QString
+ getIconName() const override
{
- class SanitizeCloudTool : public ModifyItemTool
- {
- Q_OBJECT
- public:
- SanitizeCloudTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Sanitize Cloud Tool";}
- };
-
-
- class SanitizeCloudToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- ModifyItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new SanitizeCloudTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Sanitize Cloud";}
-
- QString
- getToolGroupName () const override { return "Filters";}
-
- QString
- getIconName () const override { return ":/sanitize_cloud.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- return QList <CloudComposerItem::ItemType> ();
- }
- };
-
-
-
- }
+ return ":/sanitize_cloud.png";
}
+
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ return QList<CloudComposerItem::ItemType>();
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
+namespace pcl {
+namespace cloud_composer {
+class StatisticalOutlierRemovalTool : public ModifyItemTool {
+ Q_OBJECT
+public:
+ StatisticalOutlierRemovalTool(PropertiesModel* parameter_model, QObject* parent);
-namespace pcl
-{
- namespace cloud_composer
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
{
- class StatisticalOutlierRemovalTool : public ModifyItemTool
- {
- Q_OBJECT
- public:
- StatisticalOutlierRemovalTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Statistical Outlier Removal Tool";}
- };
+ return "Statistical Outlier Removal Tool";
+ }
+};
-
- class StatisticalOutlierRemovalToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- ModifyItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new StatisticalOutlierRemovalTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Statistical Outlier Removal";}
-
- QString
- getToolGroupName () const override { return "Filters";}
-
- QString
- getIconName () const override { return ":/statistical_outlier_removal.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- return QList <CloudComposerItem::ItemType> ();
- }
- };
+class StatisticalOutlierRemovalToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ ModifyItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new StatisticalOutlierRemovalTool(parameter_model, parent);
+ }
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+ inline QString
+ getPluginName() const override
+ {
+ return "Statistical Outlier Removal";
+ }
+ QString
+ getToolGroupName() const override
+ {
+ return "Filters";
}
-}
+
+ QString
+ getIconName() const override
+ {
+ return ":/statistical_outlier_removal.png";
+ }
+
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ return QList<CloudComposerItem::ItemType>();
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
- /*
- * Software License Agreement (BSD License)
- *
- * Point Cloud Library (PCL) - www.pointclouds.org
- * Copyright (c) 2012, Jeremie Papon.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Willow Garage, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2012, Jeremie Papon.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
#pragma once
-
- #include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
- #include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-
-
- namespace pcl
- {
- namespace cloud_composer
- {
- class SupervoxelsTool : public SplitItemTool
- {
- Q_OBJECT
- public:
- SupervoxelsTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- template <typename PointT> QList <CloudComposerItem*>
- performTemplatedAction (const QList <const CloudComposerItem*>& input_data);
-
- inline QString
- getToolName () const override { return "Voxel Superpixels Tool";}
-
-
- };
-
-
- class SupervoxelsToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- SplitItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new SupervoxelsTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Supervoxels";}
-
- inline QString
- getToolGroupName () const override { return "Segmentation";}
-
- inline QString
- getIconName () const override { return ":/supervoxels.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- QList <CloudComposerItem::ItemType> input_types;
- return input_types;
- }
- };
-
-
-
- }
- }
+
+#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
+#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
+
+namespace pcl {
+namespace cloud_composer {
+class SupervoxelsTool : public SplitItemTool {
+ Q_OBJECT
+public:
+ SupervoxelsTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ template <typename PointT>
+ QList<CloudComposerItem*>
+ performTemplatedAction(const QList<const CloudComposerItem*>& input_data);
+
+ inline QString
+ getToolName() const override
+ {
+ return "Voxel Superpixels Tool";
+ }
+};
+
+class SupervoxelsToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ SplitItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new SupervoxelsTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
+ {
+ return "Supervoxels";
+ }
+
+ inline QString
+ getToolGroupName() const override
+ {
+ return "Segmentation";
+ }
+
+ inline QString
+ getIconName() const override
+ {
+ return ":/supervoxels.png";
+ }
+
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ QList<CloudComposerItem::ItemType> input_types;
+ return input_types;
+ }
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-namespace pcl
-{
- namespace cloud_composer
+namespace pcl {
+namespace cloud_composer {
+class VoxelGridDownsampleTool : public ModifyItemTool {
+ Q_OBJECT
+public:
+ VoxelGridDownsampleTool(PropertiesModel* parameter_model, QObject* parent);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+
+ inline QString
+ getToolName() const override
+ {
+ return "Voxel Grid Downsample Tool";
+ }
+};
+
+class VoxelGridDownsampleToolFactory : public QObject, public ToolFactory {
+ Q_OBJECT
+ Q_INTERFACES(pcl::cloud_composer::ToolFactory)
+ Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
+public:
+ ModifyItemTool*
+ createTool(PropertiesModel* parameter_model, QObject* parent = nullptr) override
+ {
+ return new VoxelGridDownsampleTool(parameter_model, parent);
+ }
+
+ PropertiesModel*
+ createToolParameterModel(QObject* parent) override;
+
+ inline QString
+ getPluginName() const override
{
- class VoxelGridDownsampleTool : public ModifyItemTool
- {
- Q_OBJECT
- public:
- VoxelGridDownsampleTool (PropertiesModel* parameter_model, QObject* parent);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Voxel Grid Downsample Tool";}
- };
+ return "Voxel Grid Downsample";
+ }
-
- class VoxelGridDownsampleToolFactory : public QObject, public ToolFactory
- {
- Q_OBJECT
- Q_INTERFACES (pcl::cloud_composer::ToolFactory)
- Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
- public:
- ModifyItemTool*
- createTool (PropertiesModel* parameter_model, QObject* parent = nullptr) override
- {
- return new VoxelGridDownsampleTool(parameter_model, parent);
- }
-
- PropertiesModel*
- createToolParameterModel (QObject* parent) override;
-
- inline QString
- getPluginName () const override { return "Voxel Grid Downsample";}
-
- QString
- getToolGroupName () const override { return "Filters";}
-
- QString
- getIconName () const override { return ":/voxel_grid_downsample.png"; }
-
- inline CloudComposerItem::ItemType
- getInputItemType () const override
- {
- return CloudComposerItem::CLOUD_ITEM;
- }
-
- inline QList <CloudComposerItem::ItemType>
- getRequiredInputChildrenTypes () const override
- {
- return QList <CloudComposerItem::ItemType> ();
- }
- };
+ QString
+ getToolGroupName() const override
+ {
+ return "Filters";
+ }
+ QString
+ getIconName() const override
+ {
+ return ":/voxel_grid_downsample.png";
+ }
+ inline CloudComposerItem::ItemType
+ getInputItemType() const override
+ {
+ return CloudComposerItem::CLOUD_ITEM;
+ }
+ inline QList<CloudComposerItem::ItemType>
+ getRequiredInputChildrenTypes() const override
+ {
+ return QList<CloudComposerItem::ItemType>();
}
-}
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
-namespace pcl
-{
- namespace cloud_composer
- {
- class TransformClouds : public ModifyItemTool
- {
- Q_OBJECT
- public:
- TransformClouds (QMap <QString, vtkSmartPointer<vtkMatrix4x4> > transform_map, QObject* parent = nullptr);
-
- QList <CloudComposerItem*>
- performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
-
- inline QString
- getToolName () const override { return "Transform Clouds Tool";}
-
- template <typename PointT> QList <CloudComposerItem*>
- performTemplatedAction (const QList <const CloudComposerItem*>& input_data);
-
- private:
- QMap <QString, vtkSmartPointer<vtkMatrix4x4> > transform_map_;
- };
+namespace pcl {
+namespace cloud_composer {
+class TransformClouds : public ModifyItemTool {
+ Q_OBJECT
+public:
+ TransformClouds(QMap<QString, vtkSmartPointer<vtkMatrix4x4>> transform_map,
+ QObject* parent = nullptr);
+
+ QList<CloudComposerItem*>
+ performAction(QList<const CloudComposerItem*> input_data,
+ PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
+ inline QString
+ getToolName() const override
+ {
+ return "Transform Clouds Tool";
}
-}
+
+ template <typename PointT>
+ QList<CloudComposerItem*>
+ performTemplatedAction(const QList<const CloudComposerItem*>& input_data);
+
+private:
+ QMap<QString, vtkSmartPointer<vtkMatrix4x4>> transform_map_;
+};
+
+} // namespace cloud_composer
+} // namespace pcl
#pragma once
+#include <pcl/apps/cloud_composer/commands.h>
+
#include <QQueue>
-#include <pcl/apps/cloud_composer/commands.h>
+namespace pcl {
+namespace cloud_composer {
+class AbstractTool;
+class CloudComposerItem;
+
+struct ActionPair {
+ CloudCommand* command;
+ AbstractTool* tool;
+};
+
+class WorkQueue : public QObject {
+ Q_OBJECT
+public:
+ WorkQueue(QObject* parent = nullptr);
+public Q_SLOTS:
+ void
+ enqueueNewAction(AbstractTool* new_tool, ConstItemList input_data);
+
+ void
+ actionFinished(ActionPair finished_action);
+
+ void
+ checkQueue();
+Q_SIGNALS:
+ void
+ commandProgress(QString command_text, double progress);
-namespace pcl
-{
- namespace cloud_composer
- {
- class AbstractTool;
- class CloudComposerItem;
-
- struct ActionPair
- {
- CloudCommand* command;
- AbstractTool* tool;
- };
-
- class WorkQueue : public QObject
- {
- Q_OBJECT
- public:
- WorkQueue (QObject* parent = nullptr);
- public Q_SLOTS:
- void
- enqueueNewAction (AbstractTool* new_tool, ConstItemList input_data);
-
- void
- actionFinished (ActionPair finished_action);
-
- void
- checkQueue ();
- Q_SIGNALS:
- void
- commandProgress (QString command_text, double progress);
+ void
+ commandComplete(CloudCommand* completed_command);
- void
- commandComplete (CloudCommand* completed_command);
-
- private:
- QQueue <ActionPair> work_queue_;
-
- };
- }
-}
+private:
+ QQueue<ActionPair> work_queue_;
+};
+} // namespace cloud_composer
+} // namespace pcl
#include <pcl/apps/cloud_composer/cloud_composer.h>
-#include <pcl/apps/cloud_composer/project_model.h>
-#include <pcl/apps/cloud_composer/cloud_viewer.h>
#include <pcl/apps/cloud_composer/cloud_view.h>
-#include <pcl/apps/cloud_composer/item_inspector.h>
+#include <pcl/apps/cloud_composer/cloud_viewer.h>
#include <pcl/apps/cloud_composer/commands.h>
-#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
+#include <pcl/apps/cloud_composer/item_inspector.h>
+#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
+#include <pcl/apps/cloud_composer/project_model.h>
+#include <pcl/apps/cloud_composer/signal_multiplexer.h>
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
+#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
#include <pcl/apps/cloud_composer/toolbox_model.h>
-#include <pcl/apps/cloud_composer/signal_multiplexer.h>
-#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
#include <QActionGroup>
#include <QMessageBox>
#include <QUndoGroup>
/////////////////////////////////////////////////////////////
-pcl::cloud_composer::ComposerMainWindow::ComposerMainWindow (QWidget *parent)
- : QMainWindow (parent)
+pcl::cloud_composer::ComposerMainWindow::ComposerMainWindow(QWidget* parent)
+: QMainWindow(parent)
{
- setupUi (this);
-
- this->setCorner (Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
- this->setCorner (Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
- //Register types in Qt
- qRegisterMetaType<pcl::PCLPointCloud2::Ptr> ("PCLPointCloud2Ptr");
- qRegisterMetaType<GeometryHandler::ConstPtr> ("GeometryHandlerConstPtr");
- qRegisterMetaType<ColorHandler::ConstPtr> ("ColorHandlerConstPtr");
- qRegisterMetaType<Eigen::Vector4f> ("EigenVector4f");
- qRegisterMetaType<Eigen::Quaternionf> ("EigenQuaternionf");
- qRegisterMetaType<ProjectModel> ("ProjectModel");
- qRegisterMetaType<CloudView> ("CloudView");
- qRegisterMetaType<ConstItemList> ("ConstComposerItemList");
-
+ setupUi(this);
+
+ this->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ this->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+ // Register types in Qt
+ qRegisterMetaType<pcl::PCLPointCloud2::Ptr>("PCLPointCloud2Ptr");
+ qRegisterMetaType<GeometryHandler::ConstPtr>("GeometryHandlerConstPtr");
+ qRegisterMetaType<ColorHandler::ConstPtr>("ColorHandlerConstPtr");
+ qRegisterMetaType<Eigen::Vector4f>("EigenVector4f");
+ qRegisterMetaType<Eigen::Quaternionf>("EigenQuaternionf");
+ qRegisterMetaType<ProjectModel>("ProjectModel");
+ qRegisterMetaType<CloudView>("CloudView");
+ qRegisterMetaType<ConstItemList>("ConstComposerItemList");
+
current_model_ = nullptr;
-
- multiplexer_ = new SignalMultiplexer (this);
-
- initializeCloudBrowser ();
- initializeCloudViewer ();
- initializeItemInspector ();
- initializeToolBox ();
- initializePlugins ();
-
- undo_group_ = new QUndoGroup (this);
- undo_view_->setGroup (undo_group_);
-
- //Auto connect signals and slots
- // QMetaObject::connectSlotsByName(this);
- connectFileActions ();
- connectEditActions ();
- connectViewActions ();
-
+
+ multiplexer_ = new SignalMultiplexer(this);
+
+ initializeCloudBrowser();
+ initializeCloudViewer();
+ initializeItemInspector();
+ initializeToolBox();
+ initializePlugins();
+
+ undo_group_ = new QUndoGroup(this);
+ undo_view_->setGroup(undo_group_);
+
+ // Auto connect signals and slots
+ // QMetaObject::connectSlotsByName(this);
+ connectFileActions();
+ connectEditActions();
+ connectViewActions();
}
-pcl::cloud_composer::ComposerMainWindow::~ComposerMainWindow ()
+pcl::cloud_composer::ComposerMainWindow::~ComposerMainWindow()
{
- foreach (ProjectModel* to_delete, name_model_map_.values ())
- to_delete->deleteLater ();
+ foreach (ProjectModel* to_delete, name_model_map_.values())
+ to_delete->deleteLater();
}
void
-pcl::cloud_composer::ComposerMainWindow::connectFileActions ()
-{
-
-
-}
+pcl::cloud_composer::ComposerMainWindow::connectFileActions()
+{}
void
-pcl::cloud_composer::ComposerMainWindow::connectEditActions ()
+pcl::cloud_composer::ComposerMainWindow::connectEditActions()
{
- //Replace the actions in the menu with undo actions created using the undo group
- QAction* action_temp = undo_group_->createUndoAction (this);
- action_temp->setShortcut (action_undo_->shortcut ());
- menuEdit->insertAction (action_redo_, action_temp);
- menuEdit->removeAction (action_undo_);
+ // Replace the actions in the menu with undo actions created using the undo group
+ QAction* action_temp = undo_group_->createUndoAction(this);
+ action_temp->setShortcut(action_undo_->shortcut());
+ menuEdit->insertAction(action_redo_, action_temp);
+ menuEdit->removeAction(action_undo_);
action_undo_ = action_temp;
-
- action_temp = undo_group_->createRedoAction (this);
- action_temp->setShortcut (action_redo_->shortcut ());
- menuEdit->insertAction (action_redo_, action_temp);
- menuEdit->removeAction (action_redo_);
+
+ action_temp = undo_group_->createRedoAction(this);
+ action_temp->setShortcut(action_redo_->shortcut());
+ menuEdit->insertAction(action_redo_, action_temp);
+ menuEdit->removeAction(action_redo_);
action_redo_ = action_temp;
-
- multiplexer_->connect (action_clear_selection_, SIGNAL (triggered ()), SLOT (clearSelection ()));
-
- multiplexer_->connect (action_delete_, SIGNAL (triggered ()), SLOT (deleteSelectedItems ()));
- multiplexer_->connect (SIGNAL (deleteAvailable (bool)), action_delete_, SLOT (setEnabled (bool)));
-
- multiplexer_->connect (this, SIGNAL (insertNewCloudFromFile()), SLOT (insertNewCloudFromFile()));
- multiplexer_->connect (this, SIGNAL (insertNewCloudFromRGBandDepth()), SLOT (insertNewCloudFromRGBandDepth()));
- multiplexer_->connect (this, SIGNAL (saveSelectedCloudToFile()), SLOT (saveSelectedCloudToFile()));
-
-
- mouse_style_group_ = new QActionGroup (this);
- mouse_style_group_->addAction (action_trackball_camera_style_);
- mouse_style_group_->addAction (action_manipulate_clicked_);
- mouse_style_group_->addAction (action_manipulate_selected_);
- mouse_style_group_->addAction (action_rectangular_frustum_select_);
- mouse_style_group_->setExclusive (true);
- multiplexer_->connect (mouse_style_group_, SIGNAL (triggered (QAction*)), SLOT (mouseStyleChanged (QAction*)));
- multiplexer_->connect(SIGNAL (mouseStyleState (interactor_styles::INTERACTOR_STYLES)), this, SLOT(setMouseStyleAction(interactor_styles::INTERACTOR_STYLES)));
- action_trackball_camera_style_->setData (QVariant::fromValue (interactor_styles::PCL_VISUALIZER));
- action_rectangular_frustum_select_->setData (QVariant::fromValue (interactor_styles::RECTANGULAR_FRUSTUM));
- action_manipulate_selected_->setData (QVariant::fromValue (interactor_styles::SELECTED_TRACKBALL));
- action_manipulate_clicked_->setData (QVariant::fromValue (interactor_styles::CLICK_TRACKBALL));
- //multiplexer_->connect (action_manipulate_selected_, SIGNAL (triggered ()), SLOT (selectedTrackballInteractorStyle ()));
-
-
- multiplexer_->connect (action_new_cloud_from_selection_, SIGNAL (triggered ()), SLOT (createNewCloudFromSelection ()));
- multiplexer_->connect (SIGNAL (newCloudFromSelectionAvailable (bool)), action_new_cloud_from_selection_, SLOT (setEnabled (bool)));
-
- multiplexer_->connect (action_select_all_, SIGNAL (triggered ()), SLOT (selectAllItems ()));
+
+ multiplexer_->connect(
+ action_clear_selection_, SIGNAL(triggered()), SLOT(clearSelection()));
+
+ multiplexer_->connect(
+ action_delete_, SIGNAL(triggered()), SLOT(deleteSelectedItems()));
+ multiplexer_->connect(
+ SIGNAL(deleteAvailable(bool)), action_delete_, SLOT(setEnabled(bool)));
+
+ multiplexer_->connect(
+ this, SIGNAL(insertNewCloudFromFile()), SLOT(insertNewCloudFromFile()));
+ multiplexer_->connect(this,
+ SIGNAL(insertNewCloudFromRGBandDepth()),
+ SLOT(insertNewCloudFromRGBandDepth()));
+ multiplexer_->connect(
+ this, SIGNAL(saveSelectedCloudToFile()), SLOT(saveSelectedCloudToFile()));
+
+ mouse_style_group_ = new QActionGroup(this);
+ mouse_style_group_->addAction(action_trackball_camera_style_);
+ mouse_style_group_->addAction(action_manipulate_clicked_);
+ mouse_style_group_->addAction(action_manipulate_selected_);
+ mouse_style_group_->addAction(action_rectangular_frustum_select_);
+ mouse_style_group_->setExclusive(true);
+ multiplexer_->connect(mouse_style_group_,
+ SIGNAL(triggered(QAction*)),
+ SLOT(mouseStyleChanged(QAction*)));
+ multiplexer_->connect(
+ SIGNAL(mouseStyleState(interactor_styles::INTERACTOR_STYLES)),
+ this,
+ SLOT(setMouseStyleAction(interactor_styles::INTERACTOR_STYLES)));
+ action_trackball_camera_style_->setData(
+ QVariant::fromValue(interactor_styles::PCL_VISUALIZER));
+ action_rectangular_frustum_select_->setData(
+ QVariant::fromValue(interactor_styles::RECTANGULAR_FRUSTUM));
+ action_manipulate_selected_->setData(
+ QVariant::fromValue(interactor_styles::SELECTED_TRACKBALL));
+ action_manipulate_clicked_->setData(
+ QVariant::fromValue(interactor_styles::CLICK_TRACKBALL));
+ // multiplexer_->connect (action_manipulate_selected_, SIGNAL (triggered ()), SLOT
+ // (selectedTrackballInteractorStyle ()));
+
+ multiplexer_->connect(action_new_cloud_from_selection_,
+ SIGNAL(triggered()),
+ SLOT(createNewCloudFromSelection()));
+ multiplexer_->connect(SIGNAL(newCloudFromSelectionAvailable(bool)),
+ action_new_cloud_from_selection_,
+ SLOT(setEnabled(bool)));
+
+ multiplexer_->connect(
+ action_select_all_, SIGNAL(triggered()), SLOT(selectAllItems()));
}
void
-pcl::cloud_composer::ComposerMainWindow::setMouseStyleAction (interactor_styles::INTERACTOR_STYLES selected_style)
+pcl::cloud_composer::ComposerMainWindow::setMouseStyleAction(
+ interactor_styles::INTERACTOR_STYLES selected_style)
{
- action_trackball_camera_style_->setChecked (false);
- action_rectangular_frustum_select_->setChecked (false);
- action_manipulate_selected_->setChecked (false);
- action_manipulate_clicked_->setChecked (false);
-
- switch (selected_style)
- {
- case interactor_styles::PCL_VISUALIZER :
- action_trackball_camera_style_->setChecked (true);
- break;
- case interactor_styles::CLICK_TRACKBALL :
- action_manipulate_clicked_->setChecked (true);
- break;
- case interactor_styles::RECTANGULAR_FRUSTUM :
- action_rectangular_frustum_select_->setChecked (true);
- break;
- case interactor_styles::SELECTED_TRACKBALL :
- action_manipulate_selected_->setChecked (true);
- break;
- default :
- action_trackball_camera_style_->setChecked (true);
-
+ action_trackball_camera_style_->setChecked(false);
+ action_rectangular_frustum_select_->setChecked(false);
+ action_manipulate_selected_->setChecked(false);
+ action_manipulate_clicked_->setChecked(false);
+
+ switch (selected_style) {
+ case interactor_styles::PCL_VISUALIZER:
+ action_trackball_camera_style_->setChecked(true);
+ break;
+ case interactor_styles::CLICK_TRACKBALL:
+ action_manipulate_clicked_->setChecked(true);
+ break;
+ case interactor_styles::RECTANGULAR_FRUSTUM:
+ action_rectangular_frustum_select_->setChecked(true);
+ break;
+ case interactor_styles::SELECTED_TRACKBALL:
+ action_manipulate_selected_->setChecked(true);
+ break;
+ default:
+ action_trackball_camera_style_->setChecked(true);
}
}
void
-pcl::cloud_composer::ComposerMainWindow::connectViewActions ()
+pcl::cloud_composer::ComposerMainWindow::connectViewActions()
{
- multiplexer_->connect (action_show_axes_, SIGNAL (toggled (bool)), SLOT (setAxisVisibility (bool)));
- multiplexer_->connect (SIGNAL (axisVisible (bool)), action_show_axes_, SLOT (setChecked (bool)));
-
+ multiplexer_->connect(
+ action_show_axes_, SIGNAL(toggled(bool)), SLOT(setAxisVisibility(bool)));
+ multiplexer_->connect(
+ SIGNAL(axisVisible(bool)), action_show_axes_, SLOT(setChecked(bool)));
}
void
-pcl::cloud_composer::ComposerMainWindow::initializeCloudBrowser ()
+pcl::cloud_composer::ComposerMainWindow::initializeCloudBrowser()
{
- cloud_browser_->setSelectionMode (QAbstractItemView::ExtendedSelection);
-
+ cloud_browser_->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
cloud_browser_->setStyleSheet("selection-background-color: red;");
-
}
void
-pcl::cloud_composer::ComposerMainWindow::initializeCloudViewer ()
+pcl::cloud_composer::ComposerMainWindow::initializeCloudViewer()
{
- //Signal emitted when user selects new tab (ie different project) in the viewer
- connect (cloud_viewer_, SIGNAL (newModelSelected (ProjectModel*)),
- this, SLOT (setCurrentModel (ProjectModel*)));
-
+ // Signal emitted when user selects new tab (ie different project) in the viewer
+ connect(cloud_viewer_,
+ SIGNAL(newModelSelected(ProjectModel*)),
+ this,
+ SLOT(setCurrentModel(ProjectModel*)));
}
void
-pcl::cloud_composer::ComposerMainWindow::initializeItemInspector ()
-{
-
-}
+pcl::cloud_composer::ComposerMainWindow::initializeItemInspector()
+{}
void
-pcl::cloud_composer::ComposerMainWindow::initializeToolBox ()
+pcl::cloud_composer::ComposerMainWindow::initializeToolBox()
{
- tool_box_model_ = new ToolBoxModel (tool_box_view_, tool_parameter_view_,this);
- tool_selection_model_ = new QItemSelectionModel (tool_box_model_);
- tool_box_model_->setSelectionModel (tool_selection_model_);
-
- tool_box_view_->setModel (tool_box_model_);
- tool_box_view_->setSelectionModel (tool_selection_model_);
- tool_box_view_->setIconSize (QSize (32,32));
- tool_box_view_->setIndentation (10);
-
- connect ( tool_selection_model_, SIGNAL (currentChanged (const QModelIndex&, const QModelIndex&)),
- tool_box_model_, SLOT (selectedToolChanged (const QModelIndex&, const QModelIndex&)));
-
- connect ( tool_box_model_, SIGNAL (enqueueToolAction (AbstractTool*)),
- this, SLOT (enqueueToolAction (AbstractTool*)));
-
- connect (this, SIGNAL (activeProjectChanged (ProjectModel*,ProjectModel*)),
- tool_box_model_, SLOT (activeProjectChanged (ProjectModel*,ProjectModel*)));
-
- //TODO : Remove this, tools should have a better way of being run
- connect ( action_run_tool_, SIGNAL (clicked ()),
- tool_box_model_, SLOT (toolAction ()));
- //tool_box_view_->setStyleSheet("branch:has-siblings:!adjoins-item:image none");
- // tool_box_view_->setStyleSheet("branch:!has-children:!has-siblings:adjoins-item:image: none");
-
-
+ tool_box_model_ = new ToolBoxModel(tool_box_view_, tool_parameter_view_, this);
+ tool_selection_model_ = new QItemSelectionModel(tool_box_model_);
+ tool_box_model_->setSelectionModel(tool_selection_model_);
+
+ tool_box_view_->setModel(tool_box_model_);
+ tool_box_view_->setSelectionModel(tool_selection_model_);
+ tool_box_view_->setIconSize(QSize(32, 32));
+ tool_box_view_->setIndentation(10);
+
+ connect(tool_selection_model_,
+ SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
+ tool_box_model_,
+ SLOT(selectedToolChanged(const QModelIndex&, const QModelIndex&)));
+
+ connect(tool_box_model_,
+ SIGNAL(enqueueToolAction(AbstractTool*)),
+ this,
+ SLOT(enqueueToolAction(AbstractTool*)));
+
+ connect(this,
+ SIGNAL(activeProjectChanged(ProjectModel*, ProjectModel*)),
+ tool_box_model_,
+ SLOT(activeProjectChanged(ProjectModel*, ProjectModel*)));
+
+ // TODO : Remove this, tools should have a better way of being run
+ connect(action_run_tool_, SIGNAL(clicked()), tool_box_model_, SLOT(toolAction()));
+ // tool_box_view_->setStyleSheet("branch:has-siblings:!adjoins-item:image none");
+ // tool_box_view_->setStyleSheet("branch:!has-children:!has-siblings:adjoins-item:image:
+ // none");
}
-
-void
-pcl::cloud_composer::ComposerMainWindow::initializePlugins ()
+void
+pcl::cloud_composer::ComposerMainWindow::initializePlugins()
{
- QDir plugin_dir = QCoreApplication::applicationDirPath ();
- qDebug() << plugin_dir.path ()<< " "<<QDir::cleanPath ("../lib/cloud_composer_plugins");
+ QDir plugin_dir = QCoreApplication::applicationDirPath();
+ qDebug() << plugin_dir.path() << " "
+ << QDir::cleanPath("../lib/cloud_composer_plugins");
#ifdef _WIN32
- if (!plugin_dir.cd (QDir::cleanPath ("cloud_composer_plugins")))
+ if (!plugin_dir.cd(QDir::cleanPath("cloud_composer_plugins")))
#else
- if (!plugin_dir.cd (QDir::cleanPath ("../lib/cloud_composer_plugins")))
+ if (!plugin_dir.cd(QDir::cleanPath("../lib/cloud_composer_plugins")))
#endif
{
- #ifdef _WIN32
- if (!plugin_dir.cd (QDir::cleanPath ("cloud_composer_plugins")))
- #else
- if (!plugin_dir.cd (QDir::cleanPath ("../lib")))
- #endif
- {
- qCritical () << "Could not find plugin tool directory!!!";
- }
+#ifdef _WIN32
+ if (!plugin_dir.cd(QDir::cleanPath("cloud_composer_plugins")))
+#else
+ if (!plugin_dir.cd(QDir::cleanPath("../lib")))
+#endif
+ {
+ qCritical() << "Could not find plugin tool directory!!!";
+ }
}
QStringList plugin_filter;
#ifdef _WIN32
#else
plugin_filter << "libpcl_cc_tool_*.so";
#endif
- plugin_dir.setNameFilters (plugin_filter);
- foreach (QString filename, plugin_dir.entryList (QDir::Files))
- {
- qDebug () << "Loading " << plugin_dir.relativeFilePath (filename);
- QPluginLoader loader (plugin_dir.absoluteFilePath (filename), this);
+ plugin_dir.setNameFilters(plugin_filter);
+ foreach (QString filename, plugin_dir.entryList(QDir::Files)) {
+ qDebug() << "Loading " << plugin_dir.relativeFilePath(filename);
+ QPluginLoader loader(plugin_dir.absoluteFilePath(filename), this);
// This is automatically deleted when the library is unloaded (on app exit)
- QObject *plugin = loader.instance ();
- ToolFactory* tool_factory = qobject_cast <ToolFactory*> (plugin);
+ QObject* plugin = loader.instance();
+ ToolFactory* tool_factory = qobject_cast<ToolFactory*>(plugin);
if (tool_factory) {
- qWarning () << "Loaded " << tool_factory->getPluginName ();
- //Create the action button for this tool
- tool_box_model_->addTool (tool_factory);
-
+ qWarning() << "Loaded " << tool_factory->getPluginName();
+ // Create the action button for this tool
+ tool_box_model_->addTool(tool_factory);
}
- else{
- qDebug() << "Could not load " << plugin_dir.relativeFilePath (filename);
- qDebug() << loader.errorString ();
+ else {
+ qDebug() << "Could not load " << plugin_dir.relativeFilePath(filename);
+ qDebug() << loader.errorString();
}
-
}
}
-
-
-void
-pcl::cloud_composer::ComposerMainWindow::setCurrentModel (ProjectModel* model)
+void
+pcl::cloud_composer::ComposerMainWindow::setCurrentModel(ProjectModel* model)
{
- emit activeProjectChanged (model, current_model_);
+ emit activeProjectChanged(model, current_model_);
current_model_ = model;
- //qDebug () << "Setting cloud browser model";
- cloud_browser_->setModel (current_model_);
- //qDebug () << "Setting cloud browser selection model";
- cloud_browser_->setSelectionModel (current_model_->getSelectionModel ());
- //qDebug () << "Item inspector setting model";
- item_inspector_->setModel (current_model_);
- //qDebug () << "Setting active stack in undo group";
- undo_group_->setActiveStack (current_model_->getUndoStack ());
-
- multiplexer_->setCurrentObject (current_model_);
+ // qDebug () << "Setting cloud browser model";
+ cloud_browser_->setModel(current_model_);
+ // qDebug () << "Setting cloud browser selection model";
+ cloud_browser_->setSelectionModel(current_model_->getSelectionModel());
+ // qDebug () << "Item inspector setting model";
+ item_inspector_->setModel(current_model_);
+ // qDebug () << "Setting active stack in undo group";
+ undo_group_->setActiveStack(current_model_->getUndoStack());
+
+ multiplexer_->setCurrentObject(current_model_);
}
void
-pcl::cloud_composer::ComposerMainWindow::enqueueToolAction (AbstractTool* tool)
+pcl::cloud_composer::ComposerMainWindow::enqueueToolAction(AbstractTool* tool)
{
if (current_model_)
- current_model_->enqueueToolAction (tool);
+ current_model_->enqueueToolAction(tool);
else
- QMessageBox::warning (this, "No Project Open!", "Cannot use tool, no project is open!");
+ QMessageBox::warning(
+ this, "No Project Open!", "Cannot use tool, no project is open!");
}
///////// FILE MENU SLOTS ///////////
-void
-pcl::cloud_composer::ComposerMainWindow::on_action_new_project__triggered (/*QString name*/)
+void pcl::cloud_composer::ComposerMainWindow::on_action_new_project__triggered(
+ /*QString name*/)
{
QString name("unsaved project");
- qDebug () << "Creating New Project";
- ProjectModel* new_project_model = new ProjectModel (this);
+ qDebug() << "Creating New Project";
+ ProjectModel* new_project_model = new ProjectModel(this);
// Check if we have a project with this name already, append int if so
- if (name_model_map_.contains (name))
- {
+ if (name_model_map_.contains(name)) {
int k = 2;
- while (name_model_map_.contains (name + tr ("-%1").arg (k)))
+ while (name_model_map_.contains(name + tr("-%1").arg(k)))
++k;
- name += tr ("-%1").arg (k);
+ name += tr("-%1").arg(k);
}
- //qDebug () << "Setting name";
- new_project_model->setName (name);
- //qDebug () << "Inserting into map";
- name_model_map_.insert (name,new_project_model);
- //qDebug () << "Adding to undo group";
- undo_group_->addStack (new_project_model->getUndoStack ());
- //qDebug () << "Setting current model";
- cloud_viewer_->addNewProject (new_project_model);
-
- setCurrentModel (new_project_model);
- //qDebug () << "Project " <<name<<" created!";
-
+ // qDebug () << "Setting name";
+ new_project_model->setName(name);
+ // qDebug () << "Inserting into map";
+ name_model_map_.insert(name, new_project_model);
+ // qDebug () << "Adding to undo group";
+ undo_group_->addStack(new_project_model->getUndoStack());
+ // qDebug () << "Setting current model";
+ cloud_viewer_->addNewProject(new_project_model);
+
+ setCurrentModel(new_project_model);
+ // qDebug () << "Project " <<name<<" created!";
}
-
void
-pcl::cloud_composer::ComposerMainWindow::on_action_open_cloud_as_new_project__triggered ()
+pcl::cloud_composer::ComposerMainWindow::
+ on_action_open_cloud_as_new_project__triggered()
{
- qDebug () << "Opening cloud as new project";
+ qDebug() << "Opening cloud as new project";
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_open_project__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_open_project__triggered()
{
- qDebug () << "Opening Project";
+ qDebug() << "Opening Project";
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_save_project__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_save_project__triggered()
{
- qDebug () << "Saving Project";
+ qDebug() << "Saving Project";
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_save_project_as__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_save_project_as__triggered()
{
- qDebug () << "Saving Project As...";
+ qDebug() << "Saving Project As...";
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_save_selected_cloud__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_save_selected_cloud__triggered()
{
if (current_model_)
emit saveSelectedCloudToFile();
else
- QMessageBox::warning (this, "No Project Open!", "Cannot save cloud, no project is open!");
-
+ QMessageBox::warning(
+ this, "No Project Open!", "Cannot save cloud, no project is open!");
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_exit__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_exit__triggered()
{
- qDebug () << "Exiting...";
+ qDebug() << "Exiting...";
}
///////// EDIT MENU SLOTS ////////////
void
-pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_file__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_file__triggered()
{
if (!current_model_)
- action_new_project_->trigger ();
-
- emit insertNewCloudFromFile ();
+ action_new_project_->trigger();
+
+ emit insertNewCloudFromFile();
}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_rgb_depth__triggered ()
+pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_rgb_depth__triggered()
{
if (!current_model_)
- action_new_project_->trigger ();
-
- emit insertNewCloudFromRGBandDepth ();
-}
+ action_new_project_->trigger();
+ emit insertNewCloudFromRGBandDepth();
+}
void
-pcl::cloud_composer::ComposerMainWindow::on_action_insert_from_openNi_source__triggered ()
+pcl::cloud_composer::ComposerMainWindow::
+ on_action_insert_from_openNi_source__triggered()
{
- qDebug () << "Inserting cloud from OpenNi Source...";
+ qDebug() << "Inserting cloud from OpenNi Source...";
}
-
-
-
+#include <pcl/apps/cloud_composer/cloud_view.h>
#include <pcl/apps/cloud_composer/cloud_viewer.h>
#include <pcl/apps/cloud_composer/project_model.h>
-#include <pcl/apps/cloud_composer/cloud_view.h>
#include <QItemSelection>
-pcl::cloud_composer::CloudViewer::CloudViewer (QWidget* parent)
- : QTabWidget (parent)
+pcl::cloud_composer::CloudViewer::CloudViewer(QWidget* parent) : QTabWidget(parent)
{
- connect (this, SIGNAL (currentChanged (int)),
- this, SLOT (modelChanged (int)));
+ connect(this, SIGNAL(currentChanged(int)), this, SLOT(modelChanged(int)));
}
void
-pcl::cloud_composer::CloudViewer::addModel (ProjectModel* new_model)
+pcl::cloud_composer::CloudViewer::addModel(ProjectModel* new_model)
{
- CloudView* new_view = new CloudView (new_model);
- connect (new_model->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)),
- new_view, SLOT (selectedItemChanged (QItemSelection,QItemSelection)));
- new_model->setCloudView (new_view);
-
- QStandardItem* title = new_model->horizontalHeaderItem (0);
- this->addTab (new_view, title->text ());
-
- model_view_map_.insert (new_model,new_view);
-
- setCurrentWidget (model_view_map_.value (new_model));
- //Refresh the view
- new_view->refresh ();
+ CloudView* new_view = new CloudView(new_model);
+ connect(new_model->getSelectionModel(),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ new_view,
+ SLOT(selectedItemChanged(QItemSelection, QItemSelection)));
+ new_model->setCloudView(new_view);
+
+ QStandardItem* title = new_model->horizontalHeaderItem(0);
+ this->addTab(new_view, title->text());
+ model_view_map_.insert(new_model, new_view);
+
+ setCurrentWidget(model_view_map_.value(new_model));
+ // Refresh the view
+ new_view->refresh();
}
-
+
pcl::cloud_composer::ProjectModel*
-pcl::cloud_composer::CloudViewer::getModel () const
+pcl::cloud_composer::CloudViewer::getModel() const
{
if (this->count() == 0)
return nullptr;
- return dynamic_cast<CloudView*> (currentWidget ())->getModel ();
+ return dynamic_cast<CloudView*>(currentWidget())->getModel();
}
void
-pcl::cloud_composer::CloudViewer::addNewProject (ProjectModel* new_model)
+pcl::cloud_composer::CloudViewer::addNewProject(ProjectModel* new_model)
{
- //If we're already there, abort
- if (new_model == getModel ())
+ // If we're already there, abort
+ if (new_model == getModel())
return;
- //Check whether we've seen the model yet
- if ( !model_view_map_.contains (new_model))
- {
- addModel (new_model);
+ // Check whether we've seen the model yet
+ if (!model_view_map_.contains(new_model)) {
+ addModel(new_model);
}
- else
- {
- setCurrentWidget (model_view_map_.value (new_model));
- //Refresh the view
- model_view_map_.value (new_model)->refresh ();
+ else {
+ setCurrentWidget(model_view_map_.value(new_model));
+ // Refresh the view
+ model_view_map_.value(new_model)->refresh();
}
}
void
-pcl::cloud_composer::CloudViewer::modelChanged (int)
+pcl::cloud_composer::CloudViewer::modelChanged(int)
{
- emit newModelSelected (getModel ());
+ emit newModelSelected(getModel());
}
-
#include <pcl/apps/cloud_composer/commands.h>
-#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
-#include <pcl/apps/cloud_composer/project_model.h>
#include <pcl/apps/cloud_composer/merge_selection.h>
+#include <pcl/apps/cloud_composer/project_model.h>
+#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
-pcl::cloud_composer::CloudCommand::CloudCommand (QList <const CloudComposerItem*> input_data, QUndoCommand* parent)
- : QUndoCommand (parent)
- , original_data_ (std::move(input_data))
- , can_use_templates_(false)
- , template_type_ (-1)
-{
-
-}
+pcl::cloud_composer::CloudCommand::CloudCommand(
+ QList<const CloudComposerItem*> input_data, QUndoCommand* parent)
+: QUndoCommand(parent)
+, original_data_(std::move(input_data))
+, can_use_templates_(false)
+, template_type_(-1)
+{}
-pcl::cloud_composer::CloudCommand::~CloudCommand ()
+pcl::cloud_composer::CloudCommand::~CloudCommand()
{
- qDebug () << "Command Destructor";
- //If we have removed items, we delete them
- if (!last_was_undo_)
- {
- qDebug () << "Last was redo, removing original items ";
- QList <QStandardItem*> items_to_remove = removed_to_parent_map_.keys ();
- foreach (QStandardItem* to_remove, items_to_remove)
- {
- delete to_remove;
+ qDebug() << "Command Destructor";
+ // If we have removed items, we delete them
+ if (!last_was_undo_) {
+ qDebug() << "Last was redo, removing original items ";
+ QList<QStandardItem*> items_to_remove = removed_to_parent_map_.keys();
+ foreach (QStandardItem* to_remove, items_to_remove) {
+ delete to_remove;
}
}
- else
- {
- qDebug () << "Last was undo, removing new items";
- foreach (OutputPair output_pair, output_data_)
- {
- QList <CloudComposerItem*> new_items = output_pair.output_items_;
- foreach (CloudComposerItem* item, new_items)
- {
+ else {
+ qDebug() << "Last was undo, removing new items";
+ foreach (OutputPair output_pair, output_data_) {
+ QList<CloudComposerItem*> new_items = output_pair.output_items_;
+ foreach (CloudComposerItem* item, new_items) {
delete item;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::CloudCommand::setProjectModel (ProjectModel* model)
+pcl::cloud_composer::CloudCommand::setProjectModel(ProjectModel* model)
{
project_model_ = model;
}
bool
-pcl::cloud_composer::CloudCommand::canUseTemplates (ConstItemList &input_data)
+pcl::cloud_composer::CloudCommand::canUseTemplates(ConstItemList& input_data)
{
- //Make sure the input list isn't empty
- if (input_data.empty ())
- {
- qCritical () << "Cannot call a templated tool on an empty input in CloudCommand::executeToolOnTemplateCloud!";
+ // Make sure the input list isn't empty
+ if (input_data.empty()) {
+ qCritical() << "Cannot call a templated tool on an empty input in "
+ "CloudCommand::executeToolOnTemplateCloud!";
template_type_ = -2;
return false;
}
- //Make sure all input items are clouds
- QList <const CloudItem*> cloud_items;
- foreach (const CloudComposerItem* item, input_data)
- {
- const CloudItem* cloud_item = dynamic_cast<const CloudItem*> (item);
+ // Make sure all input items are clouds
+ QList<const CloudItem*> cloud_items;
+ foreach (const CloudComposerItem* item, input_data) {
+ const CloudItem* cloud_item = dynamic_cast<const CloudItem*>(item);
if (cloud_item)
- cloud_items.append (cloud_item);
+ cloud_items.append(cloud_item);
}
- if (cloud_items.size () != input_data.size ())
- {
- qCritical () << "All input items are not clouds in CloudCommand::executeToolOnTemplateCloud!";
+ if (cloud_items.size() != input_data.size()) {
+ qCritical() << "All input items are not clouds in "
+ "CloudCommand::executeToolOnTemplateCloud!";
template_type_ = -3;
return false;
}
-
+
// Now make sure all input clouds have the same templated type
- int type = cloud_items.value (0)->getPointType ();
- foreach (const CloudItem* cloud_item, cloud_items)
- {
- if (cloud_item->getPointType () != type)
- {
- qCritical () << "All input point cloud template types in CloudCommand::executeToolOnTemplateCloud are not the same!";
- qCritical () << cloud_item->text () << "'s type does not match "<<cloud_items.value (0)->type ();
+ int type = cloud_items.value(0)->getPointType();
+ foreach (const CloudItem* cloud_item, cloud_items) {
+ if (cloud_item->getPointType() != type) {
+ qCritical() << "All input point cloud template types in "
+ "CloudCommand::executeToolOnTemplateCloud are not the same!";
+ qCritical() << cloud_item->text() << "'s type does not match "
+ << cloud_items.value(0)->type();
template_type_ = -3;
return false;
}
}
/*
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::CloudCommand::executeToolOnTemplateCloud (AbstractTool* tool, ConstItemList &input_data)
+QList <pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::CloudCommand::executeToolOnTemplateCloud (AbstractTool* tool,
+ConstItemList &input_data)
{
QList <CloudComposerItem*> output;
// If can_use_templates_ is false and type is -1 we haven't checked if we can yet
if (!can_use_templates_ && template_type_ == -1)
this->canUseTemplates (input_data);
-
-
+
+
//If this is true now, we can go ahead and run it
if (can_use_templates_ && template_type_ >= 0)
{
- output = tool->performAction( input_data, static_cast<PointTypeFlags::PointType> (template_type_));
+ output = tool->performAction( input_data, static_cast<PointTypeFlags::PointType>
+(template_type_));
}
else
{
- qDebug () << "Tried CloudCommand::executeToolOnTemplateCloud but input data was not templated clouds!";
+ qDebug () << "Tried CloudCommand::executeToolOnTemplateCloud but input data was not
+templated clouds!";
}
return output;
-
+
}
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-bool
-pcl::cloud_composer::CloudCommand::replaceOriginalWithNew (const QList <const CloudComposerItem*>& originals, const QList <CloudComposerItem*>& new_items)
-{
- //Find the input item's parent
- if (originals.empty ())
- {
- qCritical () << "No items to replace specified!";
+bool
+pcl::cloud_composer::CloudCommand::replaceOriginalWithNew(
+ const QList<const CloudComposerItem*>& originals,
+ const QList<CloudComposerItem*>& new_items)
+{
+ // Find the input item's parent
+ if (originals.empty()) {
+ qCritical() << "No items to replace specified!";
return false;
}
-
- QStandardItem* parent_item = originals.value(0)->parent ();
- //Verify that all items have same parent
- foreach (const CloudComposerItem* item, originals)
- {
- if (item->parent () != parent_item)
- {
- qCritical () << "All original items must have same parent!";
+
+ QStandardItem* parent_item = originals.value(0)->parent();
+ // Verify that all items have same parent
+ foreach (const CloudComposerItem* item, originals) {
+ if (item->parent() != parent_item) {
+ qCritical() << "All original items must have same parent!";
return false;
}
}
// If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it... boo!)
if (parent_item == nullptr)
- parent_item = project_model_->invisibleRootItem ();
-
- //Now remove all the originals
- foreach (const CloudComposerItem* item, originals)
- {
- QPersistentModelIndex original_index = QPersistentModelIndex(project_model_->indexFromItem (item));
- if (!original_index.isValid ())
- {
- qCritical () << "Index of item to replace is not valid!";
+ parent_item = project_model_->invisibleRootItem();
+
+ // Now remove all the originals
+ foreach (const CloudComposerItem* item, originals) {
+ QPersistentModelIndex original_index =
+ QPersistentModelIndex(project_model_->indexFromItem(item));
+ if (!original_index.isValid()) {
+ qCritical() << "Index of item to replace is not valid!";
return false;
}
- QList <QStandardItem*> removed_items = parent_item->takeRow (original_index.row ());
- removed_to_parent_map_.insert (removed_items.value(0),parent_item);
+ QList<QStandardItem*> removed_items = parent_item->takeRow(original_index.row());
+ removed_to_parent_map_.insert(removed_items.value(0), parent_item);
}
- //Insert the new items below the parent item'
- foreach (CloudComposerItem* item, new_items)
- {
- parent_item->appendRow (item);
+ // Insert the new items below the parent item'
+ foreach (CloudComposerItem* item, new_items) {
+ parent_item->appendRow(item);
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-bool
-pcl::cloud_composer::CloudCommand::restoreOriginalRemoveNew (const QList <const CloudComposerItem*>& originals, const QList <CloudComposerItem*>& new_items)
-{
-
- //Now remove all the new items
- foreach (CloudComposerItem* item, new_items)
- {
- QStandardItem* parent_item = item->parent ();
- // If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it... boo!)
+bool
+pcl::cloud_composer::CloudCommand::restoreOriginalRemoveNew(
+ const QList<const CloudComposerItem*>& originals,
+ const QList<CloudComposerItem*>& new_items)
+{
+
+ // Now remove all the new items
+ foreach (CloudComposerItem* item, new_items) {
+ QStandardItem* parent_item = item->parent();
+ // If parent is 0, it's parent is invisiblerootitem (That's how Qt defines it...
+ // boo!)
if (parent_item == nullptr)
- parent_item = project_model_->invisibleRootItem ();
- QPersistentModelIndex to_remove_index = QPersistentModelIndex(project_model_->indexFromItem (item));
- if (!to_remove_index.isValid ())
- {
- qCritical () << "Index of item to remove while restoring originals not valid";
+ parent_item = project_model_->invisibleRootItem();
+ QPersistentModelIndex to_remove_index =
+ QPersistentModelIndex(project_model_->indexFromItem(item));
+ if (!to_remove_index.isValid()) {
+ qCritical() << "Index of item to remove while restoring originals not valid";
return false;
}
- //Take them, they're still stored so we don't worry about them
- QList <QStandardItem*> removed = parent_item->takeRow (to_remove_index.row ());
- }
- //Restore the original items
- foreach (const CloudComposerItem* item, originals)
- {
- //Point iterator to the correct spot
- // Find doesn't modify parameter so it should accept a const pointer, but it can't be because it is templated to the map type
- // So we hack to get around this with a const cast
- const auto& itr = removed_to_parent_map_.find (const_cast<CloudComposerItem*> (item));
- QStandardItem* parent = itr.value ();
- QStandardItem* original = itr.key ();
- parent->appendRow (original);
- int num = removed_to_parent_map_.remove (original);
+ // Take them, they're still stored so we don't worry about them
+ QList<QStandardItem*> removed = parent_item->takeRow(to_remove_index.row());
+ }
+ // Restore the original items
+ foreach (const CloudComposerItem* item, originals) {
+ // Point iterator to the correct spot
+ // Find doesn't modify parameter so it should accept a const pointer, but it can't
+ // be because it is templated to the map type So we hack to get around this with a
+ // const cast
+ const auto& itr = removed_to_parent_map_.find(const_cast<CloudComposerItem*>(item));
+ QStandardItem* parent = itr.value();
+ QStandardItem* original = itr.key();
+ parent->appendRow(original);
+ int num = removed_to_parent_map_.remove(original);
if (num > 1)
- qCritical () << "More than one item with same pointer in removed_to_parent_map_, this is undefined behavior";
- else if (num == 0)
- qCritical () << "Could not find key in map to remove, not good!";
+ qCritical() << "More than one item with same pointer in removed_to_parent_map_, "
+ "this is undefined behavior";
+ else if (num == 0)
+ qCritical() << "Could not find key in map to remove, not good!";
}
return true;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////// MODIFY CLOUD COMMAND
-pcl::cloud_composer::ModifyItemCommand::ModifyItemCommand (QList <const CloudComposerItem*> input_data, QUndoCommand* parent)
- : CloudCommand (std::move(input_data), parent)
-{
-
-}
+pcl::cloud_composer::ModifyItemCommand::ModifyItemCommand(
+ QList<const CloudComposerItem*> input_data, QUndoCommand* parent)
+: CloudCommand(std::move(input_data), parent)
+{}
bool
-pcl::cloud_composer::ModifyItemCommand::runCommand (AbstractTool* tool)
+pcl::cloud_composer::ModifyItemCommand::runCommand(AbstractTool* tool)
{
- this->setText (tool->getToolName ());
- //For modify item cloud command, each selected item should be processed separately
+ this->setText(tool->getToolName());
+ // For modify item cloud command, each selected item should be processed separately
int num_items_returned = 0;
- foreach (const CloudComposerItem *item, original_data_)
- {
- QList <const CloudComposerItem*> input_list;
- input_list.append (item);
- QList <CloudComposerItem*> output;
+ foreach (const CloudComposerItem* item, original_data_) {
+ QList<const CloudComposerItem*> input_list;
+ input_list.append(item);
+ QList<CloudComposerItem*> output;
if (canUseTemplates(input_list))
- output = tool->performAction (input_list, static_cast<PointTypeFlags::PointType> (template_type_));
+ output = tool->performAction(
+ input_list, static_cast<PointTypeFlags::PointType>(template_type_));
else
- output = tool->performAction (input_list);
- if (output.empty ())
- qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a ModifyItemCommand";
- else
- {
+ output = tool->performAction(input_list);
+ if (output.empty())
+ qWarning() << "Warning: Tool " << tool->getToolName()
+ << "returned no item in a ModifyItemCommand";
+ else {
OutputPair output_pair = {input_list, output};
- output_data_.append (output_pair);
+ output_data_.append(output_pair);
num_items_returned++;
}
- if (output.size () > 1)
- {
- qCritical () << "Tool " << tool->getToolName () << "returned multiple items in a ModifyCloudCommand";
+ if (output.size() > 1) {
+ qCritical() << "Tool " << tool->getToolName()
+ << "returned multiple items in a ModifyCloudCommand";
}
-
}
- if (num_items_returned != original_data_.size ())
- {
- qDebug () << "Modify Item command generated "<<num_items_returned<<" which does not match input of "<<original_data_.size () <<" items";
+ if (num_items_returned != original_data_.size()) {
+ qDebug() << "Modify Item command generated " << num_items_returned
+ << " which does not match input of " << original_data_.size() << " items";
return true;
}
return true;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::ModifyItemCommand::undo ()
+pcl::cloud_composer::ModifyItemCommand::undo()
{
last_was_undo_ = true;
- qDebug () << "Undo in ModifyItemCommand";
- foreach (OutputPair output_pair, output_data_)
- {
- if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_))
+ qDebug() << "Undo in ModifyItemCommand";
+ foreach (OutputPair output_pair, output_data_) {
+ if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_))
qCritical() << "Failed to restore original items in ModifyItemCommand::undo!";
}
-
-
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::ModifyItemCommand::redo ()
+pcl::cloud_composer::ModifyItemCommand::redo()
{
last_was_undo_ = false;
- foreach (OutputPair output_pair, output_data_)
- {
- //Replace the input with the output for this pair
- if (! replaceOriginalWithNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Replacement of old items with new failed in ModifyItemCommand!";
+ foreach (OutputPair output_pair, output_data_) {
+ // Replace the input with the output for this pair
+ if (!replaceOriginalWithNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Replacement of old items with new failed in ModifyItemCommand!";
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////// New Item CLOUD COMMAND ///////////////////////////////////////////////////////////////////////////
+//////////// New Item CLOUD COMMAND
+//////////////////////////////////////////////////////////////////////////////
-pcl::cloud_composer::NewItemCloudCommand::NewItemCloudCommand (QList <const CloudComposerItem*> input_data, QUndoCommand* parent)
- : CloudCommand (std::move(input_data), parent)
-{
-
-}
+pcl::cloud_composer::NewItemCloudCommand::NewItemCloudCommand(
+ QList<const CloudComposerItem*> input_data, QUndoCommand* parent)
+: CloudCommand(std::move(input_data), parent)
+{}
bool
-pcl::cloud_composer::NewItemCloudCommand::runCommand (AbstractTool* tool)
+pcl::cloud_composer::NewItemCloudCommand::runCommand(AbstractTool* tool)
{
- this->setText (tool->getToolName ());
- //For new item cloud command, each selected item should be processed separately
- //e.g. calculate normals for every selected cloud
+ this->setText(tool->getToolName());
+ // For new item cloud command, each selected item should be processed separately
+ // e.g. calculate normals for every selected cloud
int num_new_items = 0;
- foreach (const CloudComposerItem *item, original_data_)
- {
- QList <const CloudComposerItem*> input_list;
- input_list.append (item);
- QList <CloudComposerItem*> output;
+ foreach (const CloudComposerItem* item, original_data_) {
+ QList<const CloudComposerItem*> input_list;
+ input_list.append(item);
+ QList<CloudComposerItem*> output;
if (canUseTemplates(input_list))
- output = tool->performAction (input_list, static_cast<PointTypeFlags::PointType> (template_type_));
+ output = tool->performAction(
+ input_list, static_cast<PointTypeFlags::PointType>(template_type_));
else
- output = tool->performAction (input_list);
- if (output.empty ())
- qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a NewItemCloudCommand";
- else
- {
+ output = tool->performAction(input_list);
+ if (output.empty())
+ qWarning() << "Warning: Tool " << tool->getToolName()
+ << "returned no item in a NewItemCloudCommand";
+ else {
OutputPair output_pair = {input_list, output};
- output_data_.append (output_pair);
- num_new_items += output.size ();
+ output_data_.append(output_pair);
+ num_new_items += output.size();
}
-
}
- if (num_new_items > 0)
- {
- qDebug () << "New Item command generated "<<num_new_items<<" new items";
+ if (num_new_items > 0) {
+ qDebug() << "New Item command generated " << num_new_items << " new items";
return true;
}
- qWarning () << "New Item command generated no new items!";
+ qWarning() << "New Item command generated no new items!";
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::NewItemCloudCommand::undo ()
+pcl::cloud_composer::NewItemCloudCommand::undo()
{
last_was_undo_ = true;
- qDebug () << "Undo in NewItemCloudCommand";
- foreach (OutputPair output_pair, output_data_)
- {
- //Each pair can only have one input item, so get it
- const CloudComposerItem* const_input_item = output_pair.input_items_.value (0);
- QList <CloudComposerItem*> output_items = output_pair.output_items_;
- //Find the input_item index in the project_model_
- QModelIndex input_index = project_model_->indexFromItem (const_input_item);
- if (!input_index.isValid ())
- {
- qCritical () << "Index of input cloud item is no longer valid, cannot undo NewItemCloudCommand";
+ qDebug() << "Undo in NewItemCloudCommand";
+ foreach (OutputPair output_pair, output_data_) {
+ // Each pair can only have one input item, so get it
+ const CloudComposerItem* const_input_item = output_pair.input_items_.value(0);
+ QList<CloudComposerItem*> output_items = output_pair.output_items_;
+ // Find the input_item index in the project_model_
+ QModelIndex input_index = project_model_->indexFromItem(const_input_item);
+ if (!input_index.isValid()) {
+ qCritical() << "Index of input cloud item is no longer valid, cannot undo "
+ "NewItemCloudCommand";
return;
}
- //Get a copy of the input item we can modify
- QStandardItem* item_to_change = project_model_->itemFromIndex (input_index);
- //Remove the items we added
- foreach (CloudComposerItem* output_item, output_items)
- {
- QModelIndex output_index = project_model_->indexFromItem (output_item);
- item_to_change->takeRow (output_index.row ());
+ // Get a copy of the input item we can modify
+ QStandardItem* item_to_change = project_model_->itemFromIndex(input_index);
+ // Remove the items we added
+ foreach (CloudComposerItem* output_item, output_items) {
+ QModelIndex output_index = project_model_->indexFromItem(output_item);
+ item_to_change->takeRow(output_index.row());
}
-
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::NewItemCloudCommand::redo ()
+pcl::cloud_composer::NewItemCloudCommand::redo()
{
last_was_undo_ = false;
- qDebug () << "Redo in NewItemCloudCommand - output data size="<<output_data_.size ();
- foreach (OutputPair output_pair, output_data_)
- {
- //Each pair can only have one input item, so get it
- const CloudComposerItem* const_input_item = output_pair.input_items_.value (0);
- QList <CloudComposerItem*> output_items = output_pair.output_items_;
- //Find the input_item index in the project_model_
- QPersistentModelIndex input_index = QPersistentModelIndex(project_model_->indexFromItem (const_input_item));
- if (!input_index.isValid ())
- {
- qCritical () << "Index of input cloud item is no longer valid upon command completion!";
+ qDebug() << "Redo in NewItemCloudCommand - output data size=" << output_data_.size();
+ foreach (OutputPair output_pair, output_data_) {
+ // Each pair can only have one input item, so get it
+ const CloudComposerItem* const_input_item = output_pair.input_items_.value(0);
+ QList<CloudComposerItem*> output_items = output_pair.output_items_;
+ // Find the input_item index in the project_model_
+ QPersistentModelIndex input_index =
+ QPersistentModelIndex(project_model_->indexFromItem(const_input_item));
+ if (!input_index.isValid()) {
+ qCritical()
+ << "Index of input cloud item is no longer valid upon command completion!";
return;
}
- //Get a copy of the input item we can modify
- QStandardItem* input_item = (project_model_->itemFromIndex (input_index));
- //Append the output items to the input item
- foreach (CloudComposerItem* output_item, output_items)
- {
- input_item->appendRow (output_item);
+ // Get a copy of the input item we can modify
+ QStandardItem* input_item = (project_model_->itemFromIndex(input_index));
+ // Append the output items to the input item
+ foreach (CloudComposerItem* output_item, output_items) {
+ input_item->appendRow(output_item);
}
}
}
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////// Split CLOUD COMMAND ///////////////////////////////////////////////////////////////////////////
+//////////// Split CLOUD COMMAND
+//////////////////////////////////////////////////////////////////////////////
-pcl::cloud_composer::SplitCloudCommand::SplitCloudCommand (QList <const CloudComposerItem*> input_data, QUndoCommand* parent)
- : CloudCommand (std::move(input_data), parent)
-{
-
-}
+pcl::cloud_composer::SplitCloudCommand::SplitCloudCommand(
+ QList<const CloudComposerItem*> input_data, QUndoCommand* parent)
+: CloudCommand(std::move(input_data), parent)
+{}
bool
-pcl::cloud_composer::SplitCloudCommand::runCommand (AbstractTool* tool)
+pcl::cloud_composer::SplitCloudCommand::runCommand(AbstractTool* tool)
{
- this->setText (tool->getToolName ());
- //For split cloud command, each selected item should be processed separately
- //e.g. calculate normals for every selected cloud
+ this->setText(tool->getToolName());
+ // For split cloud command, each selected item should be processed separately
+ // e.g. calculate normals for every selected cloud
int num_new_items = 0;
- foreach (const CloudComposerItem *item, original_data_)
- {
- //Check to see if this is a cloud
- QList <const CloudComposerItem*> input_list;
- input_list.append (item);
- QList <CloudComposerItem*> output;
+ foreach (const CloudComposerItem* item, original_data_) {
+ // Check to see if this is a cloud
+ QList<const CloudComposerItem*> input_list;
+ input_list.append(item);
+ QList<CloudComposerItem*> output;
if (canUseTemplates(input_list))
- output = tool->performAction (input_list, static_cast<PointTypeFlags::PointType> (template_type_));
+ output = tool->performAction(
+ input_list, static_cast<PointTypeFlags::PointType>(template_type_));
else
- output = tool->performAction (input_list);
- if (output.empty ())
- qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a SplitCloudCommand";
- else
- {
- qDebug () << "Split command returned "<<output.size ()<<" items";
+ output = tool->performAction(input_list);
+ if (output.empty())
+ qWarning() << "Warning: Tool " << tool->getToolName()
+ << "returned no item in a SplitCloudCommand";
+ else {
+ qDebug() << "Split command returned " << output.size() << " items";
OutputPair output_pair = {input_list, output};
- output_data_.append (output_pair);
- num_new_items += output.size ();
+ output_data_.append(output_pair);
+ num_new_items += output.size();
}
}
- if (num_new_items > 0)
- {
- qDebug () << "Split Item command generated "<<num_new_items<<" new items";
+ if (num_new_items > 0) {
+ qDebug() << "Split Item command generated " << num_new_items << " new items";
return true;
}
- qWarning () << "Split Item command generated no new items!";
+ qWarning() << "Split Item command generated no new items!";
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::SplitCloudCommand::undo ()
+pcl::cloud_composer::SplitCloudCommand::undo()
{
last_was_undo_ = true;
- qDebug () << "Undo in SplitItemCloudCommand";
- foreach (OutputPair output_pair, output_data_)
- {
- if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Failed to restore old cloud in SplitCloudCommand::undo!";
+ qDebug() << "Undo in SplitItemCloudCommand";
+ foreach (OutputPair output_pair, output_data_) {
+ if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Failed to restore old cloud in SplitCloudCommand::undo!";
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::SplitCloudCommand::redo ()
+pcl::cloud_composer::SplitCloudCommand::redo()
{
last_was_undo_ = false;
- qDebug () << "Redo in SplitItemCloudCommand - output data size="<<output_data_.size ();
- foreach (OutputPair output_pair, output_data_)
- {
- //Replace the input with the output for this pair
- if (! replaceOriginalWithNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Replacement of old items with new failed in ModifyItemCommand!";
-
+ qDebug() << "Redo in SplitItemCloudCommand - output data size="
+ << output_data_.size();
+ foreach (OutputPair output_pair, output_data_) {
+ // Replace the input with the output for this pair
+ if (!replaceOriginalWithNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Replacement of old items with new failed in ModifyItemCommand!";
}
}
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////// Delete CLOUD COMMAND ///////////////////////////////////////////////////////////////////////////
+//////////// Delete CLOUD COMMAND
+//////////////////////////////////////////////////////////////////////////////
-pcl::cloud_composer::DeleteItemCommand::DeleteItemCommand (QList <const CloudComposerItem*> input_data, QUndoCommand* parent)
- : CloudCommand (std::move(input_data), parent)
-{
-
-}
+pcl::cloud_composer::DeleteItemCommand::DeleteItemCommand(
+ QList<const CloudComposerItem*> input_data, QUndoCommand* parent)
+: CloudCommand(std::move(input_data), parent)
+{}
bool
-pcl::cloud_composer::DeleteItemCommand::runCommand (AbstractTool*)
+pcl::cloud_composer::DeleteItemCommand::runCommand(AbstractTool*)
{
-
- //For delete item command, each selected item should be processed separately
- //e.g. delete every selected item
- foreach (const CloudComposerItem *item, original_data_)
- {
- QList <CloudComposerItem*> output;
- QList <const CloudComposerItem*> to_delete;
- to_delete.append (item);
+
+ // For delete item command, each selected item should be processed separately
+ // e.g. delete every selected item
+ foreach (const CloudComposerItem* item, original_data_) {
+ QList<CloudComposerItem*> output;
+ QList<const CloudComposerItem*> to_delete;
+ to_delete.append(item);
OutputPair output_pair = {to_delete, output};
- output_data_.append (output_pair);
- this->setText ("Delete "+item->text ());
+ output_data_.append(output_pair);
+ this->setText("Delete " + item->text());
}
- if (!original_data_.empty ())
- this->setText ("Delete multiple items");
+ if (!original_data_.empty())
+ this->setText("Delete multiple items");
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::DeleteItemCommand::undo ()
+pcl::cloud_composer::DeleteItemCommand::undo()
{
last_was_undo_ = true;
- //Add the original items back into the model
- foreach (OutputPair output_pair, output_data_)
- {
- if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Failed to restore items in DeleteItemCommand::undo!";
+ // Add the original items back into the model
+ foreach (OutputPair output_pair, output_data_) {
+ if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Failed to restore items in DeleteItemCommand::undo!";
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::DeleteItemCommand::redo ()
+pcl::cloud_composer::DeleteItemCommand::redo()
{
last_was_undo_ = false;
- qDebug () << "Redo in DeleteItemCommand - num items to delete="<<output_data_.size ();
- foreach (OutputPair output_pair, output_data_)
- {
- //Replace the input with the output for this pair
- if (! replaceOriginalWithNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Removal of items failed in DeleteItemCommand::redo";
-
+ qDebug() << "Redo in DeleteItemCommand - num items to delete=" << output_data_.size();
+ foreach (OutputPair output_pair, output_data_) {
+ // Replace the input with the output for this pair
+ if (!replaceOriginalWithNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Removal of items failed in DeleteItemCommand::redo";
}
}
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////// MERGE CLOUD COMMAND ///////////////////////////////////////////////////////////////////////////
+//////////// MERGE CLOUD COMMAND
+//////////////////////////////////////////////////////////////////////////////
-pcl::cloud_composer::MergeCloudCommand::MergeCloudCommand (ConstItemList input_data, QUndoCommand* parent)
- : CloudCommand (std::move(input_data), parent)
-{
-
-}
+pcl::cloud_composer::MergeCloudCommand::MergeCloudCommand(ConstItemList input_data,
+ QUndoCommand* parent)
+: CloudCommand(std::move(input_data), parent)
+{}
bool
-pcl::cloud_composer::MergeCloudCommand::runCommand (AbstractTool* tool)
+pcl::cloud_composer::MergeCloudCommand::runCommand(AbstractTool* tool)
{
- //In merge command, input clouds will be combined, so send them to tool together
- QList <CloudComposerItem*> output_items;
+ // In merge command, input clouds will be combined, so send them to tool together
+ QList<CloudComposerItem*> output_items;
if (canUseTemplates(original_data_))
- output_items = tool->performAction (original_data_, static_cast<PointTypeFlags::PointType> (template_type_));
+ output_items = tool->performAction(
+ original_data_, static_cast<PointTypeFlags::PointType>(template_type_));
else
- output_items = tool->performAction (original_data_);
- MergeSelection* merge_selection = dynamic_cast <MergeSelection*> (tool);
- // If this is a merge selection we need to put the partially selected items into the original data list too!
- // We didn't send them before because merge selection already knows about them (and needs to tree input list differently from selected items)
- if (merge_selection)
- {
- QList <const CloudItem*> selected_items = merge_selection->getSelectedItems();
+ output_items = tool->performAction(original_data_);
+ MergeSelection* merge_selection = dynamic_cast<MergeSelection*>(tool);
+ // If this is a merge selection we need to put the partially selected items into the
+ // original data list too! We didn't send them before because merge selection already
+ // knows about them (and needs to tree input list differently from selected items)
+ if (merge_selection) {
+ QList<const CloudItem*> selected_items = merge_selection->getSelectedItems();
foreach (const CloudItem* item, selected_items)
- original_data_.append (item);
+ original_data_.append(item);
}
OutputPair output_pair = {original_data_, output_items};
- output_data_.append (output_pair);
-
- if (output_items.empty ())
- {
- qWarning () << "Warning: Tool " << tool->getToolName () << "returned no item in a MergeCloudCommand";
+ output_data_.append(output_pair);
+
+ if (output_items.empty()) {
+ qWarning() << "Warning: Tool " << tool->getToolName()
+ << "returned no item in a MergeCloudCommand";
return false;
}
-
- this->setText ("Merge Clouds");
+
+ this->setText("Merge Clouds");
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::MergeCloudCommand::undo ()
+pcl::cloud_composer::MergeCloudCommand::undo()
{
last_was_undo_ = true;
- //Add the original items back into the model
- foreach (OutputPair output_pair, output_data_)
- {
- if (!restoreOriginalRemoveNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Failed to restore original clouds in MergeCloudCommand::undo!";
+ // Add the original items back into the model
+ foreach (OutputPair output_pair, output_data_) {
+ if (!restoreOriginalRemoveNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Failed to restore original clouds in MergeCloudCommand::undo!";
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
-pcl::cloud_composer::MergeCloudCommand::redo ()
+pcl::cloud_composer::MergeCloudCommand::redo()
{
- qDebug () << "Redo in MergeCloudCommand ";
+ qDebug() << "Redo in MergeCloudCommand ";
last_was_undo_ = false;
- //There is only one output_pair, but that's ok
- foreach (OutputPair output_pair, output_data_)
- {
- //Replace the input with the output for this pair
- // This works because all input clouds must have same parent, the root item (clouds must be on top level)
- if (! replaceOriginalWithNew (output_pair.input_items_, output_pair.output_items_))
- qCritical () << "Removal of items failed in MergeCloudCommand::redo";
-
+ // There is only one output_pair, but that's ok
+ foreach (OutputPair output_pair, output_data_) {
+ // Replace the input with the output for this pair
+ // This works because all input clouds must have same parent, the root item (clouds
+ // must be on top level)
+ if (!replaceOriginalWithNew(output_pair.input_items_, output_pair.output_items_))
+ qCritical() << "Removal of items failed in MergeCloudCommand::redo";
}
}
-
#include <QTreeView>
-pcl::cloud_composer::ItemInspector::ItemInspector (QWidget* parent)
- : QTabWidget(parent)
+pcl::cloud_composer::ItemInspector::ItemInspector(QWidget* parent) : QTabWidget(parent)
{
current_item_properties_model_ = nullptr;
current_project_model_ = nullptr;
current_selection_model_ = nullptr;
-
- parameter_view_ = new QTreeView ();
- addTab (parameter_view_, "Parameters");
-
+ parameter_view_ = new QTreeView();
+ addTab(parameter_view_, "Parameters");
}
void
-pcl::cloud_composer::ItemInspector::setModel (ProjectModel* new_model)
+pcl::cloud_composer::ItemInspector::setModel(ProjectModel* new_model)
{
// DISABLED: JUST KEEP TREES ALWAYS EXPANDED
- //If we have a model loaded, save its tree state
- //if (current_item_properties_model_)
- // storeTreeState ();
- QItemSelectionModel* new_selection_model = new_model->getSelectionModel ();
+ // If we have a model loaded, save its tree state
+ // if (current_item_properties_model_)
+ // storeTreeState ();
+ QItemSelectionModel* new_selection_model = new_model->getSelectionModel();
current_project_model_ = new_model;
-
- if (current_selection_model_)
- {
- disconnect (current_selection_model_, SIGNAL (currentChanged (const QModelIndex, const QModelIndex)),
- this, SLOT (selectionChanged (const QModelIndex, const QModelIndex)));
- removeTabs ();
-
+
+ if (current_selection_model_) {
+ disconnect(current_selection_model_,
+ SIGNAL(currentChanged(const QModelIndex, const QModelIndex)),
+ this,
+ SLOT(selectionChanged(const QModelIndex, const QModelIndex)));
+ removeTabs();
}
current_selection_model_ = new_selection_model;
- connect (current_selection_model_, SIGNAL (currentChanged (const QModelIndex, const QModelIndex)),
- this, SLOT (selectionChanged (const QModelIndex,const QModelIndex)));
-
- updateView ();
-
+ connect(current_selection_model_,
+ SIGNAL(currentChanged(const QModelIndex, const QModelIndex)),
+ this,
+ SLOT(selectionChanged(const QModelIndex, const QModelIndex)));
+
+ updateView();
}
void
-pcl::cloud_composer::ItemInspector::selectionChanged (const QModelIndex &, const QModelIndex &)
+pcl::cloud_composer::ItemInspector::selectionChanged(const QModelIndex&,
+ const QModelIndex&)
{
- //If we have a model loaded, save its tree state
- // if (current_item_properties_model_)
- // storeTreeState ();
+ // If we have a model loaded, save its tree state
+ // if (current_item_properties_model_)
+ // storeTreeState ();
if (current_project_model_)
- updateView ();
-
+ updateView();
}
void
-pcl::cloud_composer::ItemInspector::storeTreeState ()
+pcl::cloud_composer::ItemInspector::storeTreeState()
{
- QList <QPersistentModelIndex> expanded_list;
- int row_count = current_item_properties_model_->rowCount ();
- for (int i = 0; i < row_count ; ++i)
- {
- QModelIndex index = current_item_properties_model_->index (i, 0);
- if (parameter_view_->isExpanded (index))
- {
- expanded_list << QPersistentModelIndex (index);
+ QList<QPersistentModelIndex> expanded_list;
+ int row_count = current_item_properties_model_->rowCount();
+ for (int i = 0; i < row_count; ++i) {
+ QModelIndex index = current_item_properties_model_->index(i, 0);
+ if (parameter_view_->isExpanded(index)) {
+ expanded_list << QPersistentModelIndex(index);
}
}
// save list
- item_treestate_map_.insert (current_item_properties_model_, expanded_list);
+ item_treestate_map_.insert(current_item_properties_model_, expanded_list);
}
void
-pcl::cloud_composer::ItemInspector::restoreTreeState ()
+pcl::cloud_composer::ItemInspector::restoreTreeState()
{
- if (item_treestate_map_.contains (current_item_properties_model_))
- {
- parameter_view_->setUpdatesEnabled (false);
-
- foreach (QPersistentModelIndex item_index, item_treestate_map_.value (current_item_properties_model_))
- {
- if (item_index.isValid ())
- parameter_view_->setExpanded (item_index, true);
+ if (item_treestate_map_.contains(current_item_properties_model_)) {
+ parameter_view_->setUpdatesEnabled(false);
+
+ foreach (QPersistentModelIndex item_index,
+ item_treestate_map_.value(current_item_properties_model_)) {
+ if (item_index.isValid())
+ parameter_view_->setExpanded(item_index, true);
}
- parameter_view_->setUpdatesEnabled (true);
+ parameter_view_->setUpdatesEnabled(true);
}
-
}
-void
-pcl::cloud_composer::ItemInspector::itemChanged (QStandardItem *)
-{
-
-
-}
+void
+pcl::cloud_composer::ItemInspector::itemChanged(QStandardItem*)
+{}
void
-pcl::cloud_composer::ItemInspector::removeTabs ()
+pcl::cloud_composer::ItemInspector::removeTabs()
{
- clear ();
- addTab (parameter_view_, "Parameters");
+ clear();
+ addTab(parameter_view_, "Parameters");
}
void
-pcl::cloud_composer::ItemInspector::updateView ()
+pcl::cloud_composer::ItemInspector::updateView()
{
current_item_properties_model_ = nullptr;
- QModelIndex current_item = current_selection_model_->currentIndex ();
+ QModelIndex current_item = current_selection_model_->currentIndex();
const QStandardItemModel* model = nullptr;
CloudComposerItem* cloud_item = nullptr;
- if (current_item.isValid ())
- model = dynamic_cast<const QStandardItemModel*> (current_item.model ());
-
- if (model)
- {
- cloud_item = dynamic_cast<CloudComposerItem*> (model->itemFromIndex (current_item));
- if (cloud_item)
- {
- current_item_properties_model_ = cloud_item->data (ItemDataRole::PROPERTIES).value <PropertiesModel*> ();
- //Display any additional graphical data if this item has any
- QMap <QString, QWidget*> tabs = cloud_item->getInspectorTabs ();
- foreach (QString tab_name, tabs.keys ())
- {
- addTab (tabs.value (tab_name), tab_name);
- tabs.value (tab_name)->show ();
+ if (current_item.isValid())
+ model = dynamic_cast<const QStandardItemModel*>(current_item.model());
+
+ if (model) {
+ cloud_item = dynamic_cast<CloudComposerItem*>(model->itemFromIndex(current_item));
+ if (cloud_item) {
+ current_item_properties_model_ =
+ cloud_item->data(ItemDataRole::PROPERTIES).value<PropertiesModel*>();
+ // Display any additional graphical data if this item has any
+ QMap<QString, QWidget*> tabs = cloud_item->getInspectorTabs();
+ foreach (QString tab_name, tabs.keys()) {
+ addTab(tabs.value(tab_name), tab_name);
+ tabs.value(tab_name)->show();
}
}
}
-
-
- parameter_view_->setModel (current_item_properties_model_);
- parameter_view_->resizeColumnToContents (0);
+
+ parameter_view_->setModel(current_item_properties_model_);
+ parameter_view_->resizeColumnToContents(0);
// restoreTreeState ();
- parameter_view_->expandAll ();
+ parameter_view_->expandAll();
}
#include <QDebug>
-pcl::cloud_composer::CloudComposerItem::CloudComposerItem (const QString& name)
- : QStandardItem(name)
+pcl::cloud_composer::CloudComposerItem::CloudComposerItem(const QString& name)
+: QStandardItem(name)
{
- //Set up the properties, store pointer locally for convenience
- properties_ = new PropertiesModel (this);
-
- QString item_id = name + QString ("%1").arg ((long)this);
-
-
- this->setData (QVariant::fromValue (properties_), ItemDataRole::PROPERTIES);
- this->setData (QVariant (item_id), ItemDataRole::ITEM_ID);
-
- this->setForeground (QBrush (Qt::black));
+ // Set up the properties, store pointer locally for convenience
+ properties_ = new PropertiesModel(this);
+
+ QString item_id = name + QString("%1").arg((long)this);
+
+ this->setData(QVariant::fromValue(properties_), ItemDataRole::PROPERTIES);
+ this->setData(QVariant(item_id), ItemDataRole::ITEM_ID);
+
+ this->setForeground(QBrush(Qt::black));
}
-pcl::cloud_composer::CloudComposerItem::~CloudComposerItem ()
+pcl::cloud_composer::CloudComposerItem::~CloudComposerItem()
{
- properties_->deleteLater ();
+ properties_->deleteLater();
}
pcl::cloud_composer::CloudComposerItem*
-pcl::cloud_composer::CloudComposerItem::clone () const
+pcl::cloud_composer::CloudComposerItem::clone() const
{
- CloudComposerItem* new_item = new CloudComposerItem (this->text ());
-
- PropertiesModel* new_item_properties = new_item->getPropertiesModel ();
- new_item_properties->copyProperties (properties_);
-
- return new_item;
+ CloudComposerItem* new_item = new CloudComposerItem(this->text());
+
+ PropertiesModel* new_item_properties = new_item->getPropertiesModel();
+ new_item_properties->copyProperties(properties_);
+
+ return new_item;
}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::CloudComposerItem::getChildren (CloudComposerItem::ItemType type) const
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::CloudComposerItem::getChildren(
+ CloudComposerItem::ItemType type) const
{
- QList <CloudComposerItem*> items;
- for (int i = 0; i < this->rowCount (); ++i)
- {
- if ( this->child (i)->type () == type )
- {
- items.append (dynamic_cast <CloudComposerItem*> (this->child (i)));
+ QList<CloudComposerItem*> items;
+ for (int i = 0; i < this->rowCount(); ++i) {
+ if (this->child(i)->type() == type) {
+ items.append(dynamic_cast<CloudComposerItem*>(this->child(i)));
}
}
-
+
return items;
}
-void
-pcl::cloud_composer::CloudComposerItem::addChild (CloudComposerItem *item_arg)
+void
+pcl::cloud_composer::CloudComposerItem::addChild(CloudComposerItem* item_arg)
{
- this->appendRow (item_arg);
+ this->appendRow(item_arg);
}
void
-pcl::cloud_composer::CloudComposerItem::paintView (pcl::visualization::PCLVisualizer::Ptr) const
+pcl::cloud_composer::CloudComposerItem::paintView(
+ pcl::visualization::PCLVisualizer::Ptr) const
{
- qDebug () << "Paint View in Cloud Composer Item - doing nothing";
+ qDebug() << "Paint View in Cloud Composer Item - doing nothing";
}
void
-pcl::cloud_composer::CloudComposerItem::removeFromView (pcl::visualization::PCLVisualizer::Ptr) const
+pcl::cloud_composer::CloudComposerItem::removeFromView(
+ pcl::visualization::PCLVisualizer::Ptr) const
{
- qDebug () << "Remove from View in Cloud Composer Item - doing nothing";
+ qDebug() << "Remove from View in Cloud Composer Item - doing nothing";
}
-QMap <QString, QWidget*>
-pcl::cloud_composer::CloudComposerItem::getInspectorTabs ()
+QMap<QString, QWidget*>
+pcl::cloud_composer::CloudComposerItem::getInspectorTabs()
{
- return QMap <QString, QWidget*> ();
+ return QMap<QString, QWidget*>();
}
/*
pcl::cloud_composer::CloudComposerItem::getCloudPtr () const
{
QVariant cloud_variant = this->data (CLOUD);
- // Get Extract the pointer from the cloud contained in this item, if the type can't be converted, default-constructed value is returned
- CloudPtrT ptr;
- if (cloud_variant.canConvert <CloudPtrT> ())
- ptr = cloud_variant.value <CloudPtrT> ();
+ // Get Extract the pointer from the cloud contained in this item, if the type can't be
+converted, default-constructed value is returned CloudPtrT ptr; if
+(cloud_variant.canConvert <CloudPtrT> ()) ptr = cloud_variant.value <CloudPtrT> ();
else
- qCritical () << "Requested Cloud of incorrect type from "<<this->text ()<<" correct type is "<<cloud_variant.typeName();
-
+ qCritical () << "Requested Cloud of incorrect type from "<<this->text ()<<" correct
+type is "<<cloud_variant.typeName();
+
return ptr;
}
*/
-
-
#include <pcl/apps/cloud_composer/items/fpfh_item.h>
-#include <vtkRenderWindow.h>
#include <QGridLayout>
-pcl::cloud_composer::FPFHItem::FPFHItem (QString name, const pcl::PointCloud<pcl::FPFHSignature33>::Ptr& fpfh_ptr, double radius)
- : CloudComposerItem (std::move(name))
- , fpfh_ptr_ (fpfh_ptr)
- , radius_ (radius)
+#include <vtkRenderWindow.h>
+
+pcl::cloud_composer::FPFHItem::FPFHItem(
+ QString name,
+ const pcl::PointCloud<pcl::FPFHSignature33>::Ptr& fpfh_ptr,
+ double radius)
+: CloudComposerItem(std::move(name)), fpfh_ptr_(fpfh_ptr), radius_(radius)
{
pcl::PointCloud<pcl::FPFHSignature33>::ConstPtr fpfh_const = fpfh_ptr;
- this->setData (QVariant::fromValue (fpfh_const), ItemDataRole::CLOUD_TEMPLATED);
- properties_->addCategory ("Core Properties");
- properties_->addProperty ("Radius", QVariant (radius_), Qt::ItemIsEnabled, "Core Properties");
+ this->setData(QVariant::fromValue(fpfh_const), ItemDataRole::CLOUD_TEMPLATED);
+ properties_->addCategory("Core Properties");
+ properties_->addProperty(
+ "Radius", QVariant(radius_), Qt::ItemIsEnabled, "Core Properties");
}
pcl::cloud_composer::FPFHItem*
-pcl::cloud_composer::FPFHItem::clone () const
+pcl::cloud_composer::FPFHItem::clone() const
{
- pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfh_copy (new pcl::PointCloud<pcl::FPFHSignature33> (*fpfh_ptr_));
- FPFHItem* new_item = new FPFHItem (this->text (), fpfh_copy, radius_);
-
- PropertiesModel* new_item_properties = new_item->getPropertiesModel ();
- new_item_properties->copyProperties (properties_);
-
- return new_item;
+ pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfh_copy(
+ new pcl::PointCloud<pcl::FPFHSignature33>(*fpfh_ptr_));
+ FPFHItem* new_item = new FPFHItem(this->text(), fpfh_copy, radius_);
+
+ PropertiesModel* new_item_properties = new_item->getPropertiesModel();
+ new_item_properties->copyProperties(properties_);
+
+ return new_item;
}
-QMap <QString, QWidget*>
-pcl::cloud_composer::FPFHItem::getInspectorTabs ()
-{
- //Create the plotter and QVTKWidget if it doesn't exist
- if (!plot_)
- {
- plot_.reset (new pcl::visualization::PCLPlotter);
+QMap<QString, QWidget*>
+pcl::cloud_composer::FPFHItem::getInspectorTabs()
+{
+ // Create the plotter and QVTKWidget if it doesn't exist
+ if (!plot_) {
+ plot_.reset(new pcl::visualization::PCLPlotter);
qvtk_ = new PCLQVTKWidget();
- hist_page_ = new QWidget ();
- QGridLayout *mainLayout = new QGridLayout (hist_page_);
- mainLayout-> addWidget (qvtk_,0,0);
+ hist_page_ = new QWidget();
+ QGridLayout* mainLayout = new QGridLayout(hist_page_);
+ mainLayout->addWidget(qvtk_, 0, 0);
}
- //Plot the histogram
- plot_->addFeatureHistogram (*fpfh_ptr_, fpfh_ptr_->width, data(ItemDataRole::ITEM_ID).toString().toStdString ());
- //Set the render window of the QVTK widget, update
+ // Plot the histogram
+ plot_->addFeatureHistogram(*fpfh_ptr_,
+ fpfh_ptr_->width,
+ data(ItemDataRole::ITEM_ID).toString().toStdString());
+ // Set the render window of the QVTK widget, update
plot_->setViewInteractor(getInteractorCompat(*qvtk_));
setRenderWindowCompat(*qvtk_, *(plot_->getRenderWindow()));
#if VTK_MAJOR_VERSION > 8
#else
qvtk_->update();
#endif // VTK_MAJOR_VERSION > 8
- qvtk_->show ();
-
-
- QMap <QString, QWidget*> tabs;
- tabs.insert ("Histogram",hist_page_);
+ qvtk_->show();
+
+ QMap<QString, QWidget*> tabs;
+ tabs.insert("Histogram", hist_page_);
return tabs;
}
-
-
/////////// MAIN ////////////////////
int
-main (int argc, char ** argv)
+main(int argc, char** argv)
{
// Initialize QT
- QApplication app (argc, argv);
-
+ QApplication app(argc, argv);
+
pcl::cloud_composer::ComposerMainWindow cc;
- cc.show ();
- return (QApplication::exec ());
+ cc.show();
+ return (QApplication::exec());
}
-#include <pcl/apps/cloud_composer/merge_selection.h>
+#include <pcl/apps/cloud_composer/impl/merge_selection.hpp>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
+#include <pcl/apps/cloud_composer/merge_selection.h>
#include <pcl/filters/extract_indices.h>
-#include <pcl/memory.h> // for pcl::make_shared
-#include <pcl/point_types.h>
#include <pcl/impl/instantiate.hpp>
-#include <pcl/apps/cloud_composer/impl/merge_selection.hpp>
-
-pcl::cloud_composer::MergeSelection::MergeSelection (QMap <const CloudItem*, pcl::PointIndices::ConstPtr > selected_item_index_map, QObject* parent)
- : MergeCloudTool (nullptr, parent)
- , selected_item_index_map_ (std::move(selected_item_index_map))
-{
+#include <pcl/memory.h> // for pcl::make_shared
+#include <pcl/point_types.h>
-}
+pcl::cloud_composer::MergeSelection::MergeSelection(
+ QMap<const CloudItem*, pcl::PointIndices::ConstPtr> selected_item_index_map,
+ QObject* parent)
+: MergeCloudTool(nullptr, parent)
+, selected_item_index_map_(std::move(selected_item_index_map))
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::MergeSelection::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType type)
{
- if (type != PointTypeFlags::NONE)
- {
- switch ((std::uint8_t) type)
- {
- case (PointTypeFlags::XYZ):
- return this->performTemplatedAction<pcl::PointXYZ> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
- return this->performTemplatedAction<pcl::PointXYZRGB> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
- return this->performTemplatedAction<pcl::PointXYZRGBA> (input_data);
+ if (type != PointTypeFlags::NONE) {
+ switch ((std::uint8_t)type) {
+ case (PointTypeFlags::XYZ):
+ return this->performTemplatedAction<pcl::PointXYZ>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
+ return this->performTemplatedAction<pcl::PointXYZRGB>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
+ return this->performTemplatedAction<pcl::PointXYZRGBA>(input_data);
}
}
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
// Check input data length
- if ( input_data.empty () && selected_item_index_map_.isEmpty() )
- {
- qCritical () << "Empty input in MergeSelection!";
+ if (input_data.empty() && selected_item_index_map_.isEmpty()) {
+ qCritical() << "Empty input in MergeSelection!";
return output;
}
- //Make sure all input items are cloud items
- foreach (const CloudComposerItem* input_item, input_data)
- {
- if (input_item->type () != CloudComposerItem::CLOUD_ITEM )
- {
- qCritical () << "Input in MergeSelection not valid, contained non-CloudItem input";
+ // Make sure all input items are cloud items
+ foreach (const CloudComposerItem* input_item, input_data) {
+ if (input_item->type() != CloudComposerItem::CLOUD_ITEM) {
+ qCritical() << "Input in MergeSelection not valid, contained non-CloudItem input";
return output;
}
}
pcl::ExtractIndices<pcl::PCLPointCloud2> filter;
- pcl::PCLPointCloud2::Ptr merged_cloud (new pcl::PCLPointCloud2);
- //To Save the pose of the first original item
+ pcl::PCLPointCloud2::Ptr merged_cloud(new pcl::PCLPointCloud2);
+ // To Save the pose of the first original item
Eigen::Vector4f source_origin;
Eigen::Quaternionf source_orientation;
bool pose_found = false;
- foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys ())
- {
- //If this cloud hasn't been completely selected
- if (!input_data.contains (input_cloud_item))
- {
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_cloud_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
- qDebug () << "Extracting "<<selected_item_index_map_.value(input_cloud_item)->indices.size() << " points out of "<<input_cloud->width;
- filter.setInputCloud (input_cloud);
- filter.setIndices (selected_item_index_map_.value (input_cloud_item));
- pcl::PCLPointCloud2::Ptr original_minus_indices = pcl::make_shared <pcl::PCLPointCloud2> ();
- filter.setNegative (true);
- filter.filter (*original_minus_indices);
- filter.setNegative (false);
- pcl::PCLPointCloud2::Ptr selected_points (new pcl::PCLPointCloud2);
- filter.filter (*selected_points);
+ foreach (const CloudItem* input_cloud_item, selected_item_index_map_.keys()) {
+ // If this cloud hasn't been completely selected
+ if (!input_data.contains(input_cloud_item)) {
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_cloud_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+ qDebug() << "Extracting "
+ << selected_item_index_map_.value(input_cloud_item)->indices.size()
+ << " points out of " << input_cloud->width;
+ filter.setInputCloud(input_cloud);
+ filter.setIndices(selected_item_index_map_.value(input_cloud_item));
+ pcl::PCLPointCloud2::Ptr original_minus_indices =
+ pcl::make_shared<pcl::PCLPointCloud2>();
+ filter.setNegative(true);
+ filter.filter(*original_minus_indices);
+ filter.setNegative(false);
+ pcl::PCLPointCloud2::Ptr selected_points(new pcl::PCLPointCloud2);
+ filter.filter(*selected_points);
- qDebug () << "Original minus indices is "<<original_minus_indices->width;
+ qDebug() << "Original minus indices is " << original_minus_indices->width;
- if (!pose_found)
- {
- source_origin = input_cloud_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
- source_orientation = input_cloud_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
+ if (!pose_found) {
+ source_origin =
+ input_cloud_item->data(ItemDataRole::ORIGIN).value<Eigen::Vector4f>();
+ source_orientation = input_cloud_item->data(ItemDataRole::ORIENTATION)
+ .value<Eigen::Quaternionf>();
pose_found = true;
}
- CloudItem* new_cloud_item = new CloudItem (input_cloud_item->text ()
- , original_minus_indices
- , source_origin
- , source_orientation);
- output.append (new_cloud_item);
- pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared <pcl::PCLPointCloud2> ();
- concatenate (*merged_cloud, *selected_points, *temp_cloud);
+ CloudItem* new_cloud_item = new CloudItem(input_cloud_item->text(),
+ original_minus_indices,
+ source_origin,
+ source_orientation);
+ output.append(new_cloud_item);
+ pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared<pcl::PCLPointCloud2>();
+ concatenate(*merged_cloud, *selected_points, *temp_cloud);
merged_cloud = temp_cloud;
}
- //Append the input item to the original list
- //input_data.append (input_cloud_item);
+ // Append the input item to the original list
+ // input_data.append (input_cloud_item);
}
- //Just concatenate for all fully selected clouds
- foreach (const CloudComposerItem* input_item, input_data)
- {
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
+ // Just concatenate for all fully selected clouds
+ foreach (const CloudComposerItem* input_item, input_data) {
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
- pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared <pcl::PCLPointCloud2> ();
- concatenate (*merged_cloud, *input_cloud, *temp_cloud);
+ pcl::PCLPointCloud2::Ptr temp_cloud = pcl::make_shared<pcl::PCLPointCloud2>();
+ concatenate(*merged_cloud, *input_cloud, *temp_cloud);
merged_cloud = temp_cloud;
}
- CloudItem* cloud_item = new CloudItem ("Cloud from Selection"
- , merged_cloud
- , source_origin
- , source_orientation);
+ CloudItem* cloud_item = new CloudItem(
+ "Cloud from Selection", merged_cloud, source_origin, source_orientation);
- output.append (cloud_item);
+ output.append(cloud_item);
return output;
}
#include <QDebug>
-
#include <vtkObjectFactory.h> // For vtkStandardNewMacro
#include <vtkTransform.h>
-namespace pcl
-{
- namespace cloud_composer
- {
- vtkStandardNewMacro(ClickTrackballStyleInteractor);
- }
+namespace pcl {
+namespace cloud_composer {
+vtkStandardNewMacro(ClickTrackballStyleInteractor);
}
+} // namespace pcl
-pcl::cloud_composer::ClickTrackballStyleInteractor::ClickTrackballStyleInteractor ()
+pcl::cloud_composer::ClickTrackballStyleInteractor::ClickTrackballStyleInteractor()
{
manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT;
- start_matrix_= vtkSmartPointer<vtkMatrix4x4>::New ();
- end_matrix_ = vtkSmartPointer<vtkMatrix4x4>::New ();
- transform_ = vtkSmartPointer<vtkTransform>::New ();
+ start_matrix_ = vtkSmartPointer<vtkMatrix4x4>::New();
+ end_matrix_ = vtkSmartPointer<vtkMatrix4x4>::New();
+ transform_ = vtkSmartPointer<vtkTransform>::New();
}
void
-pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonDown ()
+pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonDown()
{
vtkInteractorStyleTrackballActor::OnLeftButtonDown();
-
+
vtkActor* selected_actor = vtkActor::SafeDownCast(this->InteractionProp);
if (selected_actor)
- selected_actor->GetMatrix (start_matrix_);
-
+ selected_actor->GetMatrix(start_matrix_);
}
void
-pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonDown ()
+pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonDown()
{
vtkInteractorStyleTrackballActor::OnRightButtonDown();
-
+
vtkActor* selected_actor = vtkActor::SafeDownCast(this->InteractionProp);
if (selected_actor)
- selected_actor->GetMatrix (start_matrix_);
-
+ selected_actor->GetMatrix(start_matrix_);
}
void
-pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonUp ()
+pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonUp()
{
vtkInteractorStyleTrackballActor::OnLeftButtonUp();
- vtkSmartPointer<vtkActor> selected_actor = vtkActor::SafeDownCast(this->InteractionProp);
- if (selected_actor)
- {
- //Fetch the actor we manipulated
-
- selected_actor->GetMatrix (end_matrix_);
+ vtkSmartPointer<vtkActor> selected_actor =
+ vtkActor::SafeDownCast(this->InteractionProp);
+ if (selected_actor) {
+ // Fetch the actor we manipulated
+
+ selected_actor->GetMatrix(end_matrix_);
// Find the id of the actor we manipulated
- pcl::visualization::CloudActorMap::const_iterator end = actors_->end ();
+ pcl::visualization::CloudActorMap::const_iterator end = actors_->end();
QString manipulated_id;
- for( pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin (); itr != end; ++itr)
- {
- //qDebug () << "Id = "<<QString::fromStdString (itr->first);
- if ( (itr->second).actor == selected_actor)
- {
- manipulated_id = (QString::fromStdString (itr->first));
-
+ for (pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin();
+ itr != end;
+ ++itr) {
+ // qDebug () << "Id = "<<QString::fromStdString (itr->first);
+ if ((itr->second).actor == selected_actor) {
+ manipulated_id = (QString::fromStdString(itr->first));
}
}
- if ( !manipulated_id.isEmpty() )
- {
- ManipulationEvent* manip_event = new ManipulationEvent ();
- manip_event->addManipulation (manipulated_id, start_matrix_, end_matrix_);
- this->InvokeEvent (this->manipulation_complete_event_, manip_event);
+ if (!manipulated_id.isEmpty()) {
+ ManipulationEvent* manip_event = new ManipulationEvent();
+ manip_event->addManipulation(manipulated_id, start_matrix_, end_matrix_);
+ this->InvokeEvent(this->manipulation_complete_event_, manip_event);
}
- else
- {
- qWarning () << "Could not find actor which matches manipulated actor in ClickTrackballStyleInteractor::OnLeftButtonUp!!!";
+ else {
+ qWarning() << "Could not find actor which matches manipulated actor in "
+ "ClickTrackballStyleInteractor::OnLeftButtonUp!!!";
}
}
}
void
-pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonUp ()
+pcl::cloud_composer::ClickTrackballStyleInteractor::OnRightButtonUp()
{
vtkInteractorStyleTrackballActor::OnRightButtonUp();
- vtkSmartPointer<vtkActor> selected_actor = vtkActor::SafeDownCast(this->InteractionProp);
- if (selected_actor)
- {
- //Fetch the actor we manipulated
-
- selected_actor->GetMatrix (end_matrix_);
+ vtkSmartPointer<vtkActor> selected_actor =
+ vtkActor::SafeDownCast(this->InteractionProp);
+ if (selected_actor) {
+ // Fetch the actor we manipulated
+
+ selected_actor->GetMatrix(end_matrix_);
// Find the id of the actor we manipulated
- pcl::visualization::CloudActorMap::const_iterator end = actors_->end ();
+ pcl::visualization::CloudActorMap::const_iterator end = actors_->end();
QString manipulated_id;
- for( pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin (); itr != end; ++itr)
- {
- //qDebug () << "Id = "<<QString::fromStdString (itr->first);
- if ( (itr->second).actor == selected_actor)
- {
- manipulated_id = (QString::fromStdString (itr->first));
-
+ for (pcl::visualization::CloudActorMap::const_iterator itr = actors_->begin();
+ itr != end;
+ ++itr) {
+ // qDebug () << "Id = "<<QString::fromStdString (itr->first);
+ if ((itr->second).actor == selected_actor) {
+ manipulated_id = (QString::fromStdString(itr->first));
}
}
- if ( !manipulated_id.isEmpty() )
- {
- ManipulationEvent* manip_event = new ManipulationEvent ();
- manip_event->addManipulation (manipulated_id, start_matrix_, end_matrix_);
- this->InvokeEvent (this->manipulation_complete_event_, manip_event);
+ if (!manipulated_id.isEmpty()) {
+ ManipulationEvent* manip_event = new ManipulationEvent();
+ manip_event->addManipulation(manipulated_id, start_matrix_, end_matrix_);
+ this->InvokeEvent(this->manipulation_complete_event_, manip_event);
}
- else
- {
- qWarning () << "Could not find actor which matches manipulated actor in ClickTrackballStyleInteractor::OnRightButtonUp!!!";
+ else {
+ qWarning() << "Could not find actor which matches manipulated actor in "
+ "ClickTrackballStyleInteractor::OnRightButtonUp!!!";
}
}
-
}
-
-
+#include <pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h>
#include <pcl/apps/cloud_composer/point_selectors/interactor_style_switch.h>
#include <pcl/apps/cloud_composer/point_selectors/rectangular_frustum_selector.h>
#include <pcl/apps/cloud_composer/point_selectors/selected_trackball_interactor_style.h>
-#include <pcl/apps/cloud_composer/point_selectors/click_trackball_interactor_style.h>
#include <pcl/visualization/interactor_style.h>
#include <QDebug>
#include <vtkCallbackCommand.h>
#include <vtkObjectFactory.h>
-namespace pcl
-{
- namespace cloud_composer
- {
- vtkStandardNewMacro(InteractorStyleSwitch);
- }
+namespace pcl {
+namespace cloud_composer {
+vtkStandardNewMacro(InteractorStyleSwitch);
}
+} // namespace pcl
-pcl::cloud_composer::InteractorStyleSwitch::InteractorStyleSwitch ()
+pcl::cloud_composer::InteractorStyleSwitch::InteractorStyleSwitch()
{
- pcl_vis_style_ = vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle>::New ();
- name_to_style_map_.insert (interactor_styles::PCL_VISUALIZER, pcl_vis_style_);
-
- rectangular_frustum_selector_ = vtkSmartPointer<RectangularFrustumSelector>::New ();
- name_to_style_map_.insert (interactor_styles::RECTANGULAR_FRUSTUM, rectangular_frustum_selector_);
-
- selected_trackball_interactor_style_ = vtkSmartPointer <SelectedTrackballStyleInteractor>::New ();
- name_to_style_map_.insert (interactor_styles::SELECTED_TRACKBALL, selected_trackball_interactor_style_);
-
- click_trackball_interactor_style_ = vtkSmartPointer <ClickTrackballStyleInteractor>::New ();
- name_to_style_map_.insert (interactor_styles::CLICK_TRACKBALL, click_trackball_interactor_style_);
-
+ pcl_vis_style_ =
+ vtkSmartPointer<pcl::visualization::PCLVisualizerInteractorStyle>::New();
+ name_to_style_map_.insert(interactor_styles::PCL_VISUALIZER, pcl_vis_style_);
+
+ rectangular_frustum_selector_ = vtkSmartPointer<RectangularFrustumSelector>::New();
+ name_to_style_map_.insert(interactor_styles::RECTANGULAR_FRUSTUM,
+ rectangular_frustum_selector_);
+
+ selected_trackball_interactor_style_ =
+ vtkSmartPointer<SelectedTrackballStyleInteractor>::New();
+ name_to_style_map_.insert(interactor_styles::SELECTED_TRACKBALL,
+ selected_trackball_interactor_style_);
+
+ click_trackball_interactor_style_ =
+ vtkSmartPointer<ClickTrackballStyleInteractor>::New();
+ name_to_style_map_.insert(interactor_styles::CLICK_TRACKBALL,
+ click_trackball_interactor_style_);
+
area_picker_ = vtkSmartPointer<vtkAreaPicker>::New();
- point_picker_ = vtkSmartPointer<vtkPointPicker>::New ();
-
+ point_picker_ = vtkSmartPointer<vtkPointPicker>::New();
+
current_style_ = nullptr;
-
}
void
-pcl::cloud_composer::InteractorStyleSwitch::initializeInteractorStyles (pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model)
+pcl::cloud_composer::InteractorStyleSwitch::initializeInteractorStyles(
+ pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model)
{
- qDebug () << "Initializing Interactor Styles";
+ qDebug() << "Initializing Interactor Styles";
vis_ = std::move(vis);
project_model_ = model;
-
- pcl_vis_style_->Initialize ();
- rens_ = vis_->getRendererCollection ();
- pcl_vis_style_->setRendererCollection (rens_);
- pcl_vis_style_->setCloudActorMap (vis_->getCloudActorMap ());
-
- rectangular_frustum_selector_->setCloudActorMap (vis_->getCloudActorMap ());
-
- selected_trackball_interactor_style_->setCloudActorMap (vis_->getCloudActorMap ());
- selected_trackball_interactor_style_->setProjectModel (project_model_);
-
- click_trackball_interactor_style_->setCloudActorMap (vis_->getCloudActorMap ());
- click_trackball_interactor_style_->setProjectModel (project_model_);
+
+ pcl_vis_style_->Initialize();
+ rens_ = vis_->getRendererCollection();
+ pcl_vis_style_->setRendererCollection(rens_);
+ pcl_vis_style_->setCloudActorMap(vis_->getCloudActorMap());
+
+ rectangular_frustum_selector_->setCloudActorMap(vis_->getCloudActorMap());
+
+ selected_trackball_interactor_style_->setCloudActorMap(vis_->getCloudActorMap());
+ selected_trackball_interactor_style_->setProjectModel(project_model_);
+
+ click_trackball_interactor_style_->setCloudActorMap(vis_->getCloudActorMap());
+ click_trackball_interactor_style_->setProjectModel(project_model_);
}
void
-pcl::cloud_composer::InteractorStyleSwitch::setCurrentInteractorStyle (interactor_styles::INTERACTOR_STYLES interactor_style)
+pcl::cloud_composer::InteractorStyleSwitch::setCurrentInteractorStyle(
+ interactor_styles::INTERACTOR_STYLES interactor_style)
{
- qDebug () << "Setting interactor style";
- vtkSmartPointer <vtkInteractorStyle> style_ptr = name_to_style_map_.value (interactor_style);
+ qDebug() << "Setting interactor style";
+ vtkSmartPointer<vtkInteractorStyle> style_ptr =
+ name_to_style_map_.value(interactor_style);
if (current_style_)
- current_style_->SetInteractor (nullptr);
- current_style_= style_ptr;
-
- if (current_style_)
- {
- qDebug () << "Modifying current interactor of style!";
- current_style_->SetInteractor (this->Interactor);
- current_style_->SetTDxStyle (this->TDxStyle);
-
- if (interactor_style == interactor_styles::RECTANGULAR_FRUSTUM)
- {
- vtkInteractorStyleRubberBandPick* rubber_band_style = vtkInteractorStyleRubberBandPick::SafeDownCast (current_style_);
- if (rubber_band_style)
- {
- vis_->getRenderWindow ()->GetInteractor ()->SetPicker (area_picker_);
- rubber_band_style->StartSelect ();
+ current_style_->SetInteractor(nullptr);
+ current_style_ = style_ptr;
+
+ if (current_style_) {
+ qDebug() << "Modifying current interactor of style!";
+ current_style_->SetInteractor(this->Interactor);
+ current_style_->SetTDxStyle(this->TDxStyle);
+
+ if (interactor_style == interactor_styles::RECTANGULAR_FRUSTUM) {
+ vtkInteractorStyleRubberBandPick* rubber_band_style =
+ vtkInteractorStyleRubberBandPick::SafeDownCast(current_style_);
+ if (rubber_band_style) {
+ vis_->getRenderWindow()->GetInteractor()->SetPicker(area_picker_);
+ rubber_band_style->StartSelect();
}
}
-
-
}
-
-
-
}
//----------------------------------------------------------------------------
-void
-pcl::cloud_composer::InteractorStyleSwitch::SetInteractor (vtkRenderWindowInteractor *iren)
+void
+pcl::cloud_composer::InteractorStyleSwitch::SetInteractor(
+ vtkRenderWindowInteractor* iren)
{
- if(iren == this->Interactor)
- {
+ if (iren == this->Interactor) {
return;
}
// if we already have an Interactor then stop observing it
- if(this->Interactor)
- {
+ if (this->Interactor) {
this->Interactor->RemoveObserver(this->EventCallbackCommand);
}
this->Interactor = iren;
// add observers for each of the events handled in ProcessEvents
- if(iren)
- {
- iren->AddObserver(vtkCommand::CharEvent,
- this->EventCallbackCommand,
- this->Priority);
-
- iren->AddObserver(vtkCommand::DeleteEvent,
- this->EventCallbackCommand,
- this->Priority);
+ if (iren) {
+ iren->AddObserver(
+ vtkCommand::CharEvent, this->EventCallbackCommand, this->Priority);
+
+ iren->AddObserver(
+ vtkCommand::DeleteEvent, this->EventCallbackCommand, this->Priority);
}
}
//----------------------------------------------------------------------------
-void
-pcl::cloud_composer::InteractorStyleSwitch::SetDefaultRenderer (vtkRenderer* renderer)
+void
+pcl::cloud_composer::InteractorStyleSwitch::SetDefaultRenderer(vtkRenderer* renderer)
{
vtkInteractorStyle::SetDefaultRenderer(renderer);
pcl_vis_style_->SetDefaultRenderer(renderer);
}
//----------------------------------------------------------------------------
-void
-pcl::cloud_composer::InteractorStyleSwitch::SetCurrentRenderer (vtkRenderer* renderer)
+void
+pcl::cloud_composer::InteractorStyleSwitch::SetCurrentRenderer(vtkRenderer* renderer)
{
this->vtkInteractorStyle::SetCurrentRenderer(renderer);
pcl_vis_style_->SetCurrentRenderer(renderer);
}
void
-pcl::cloud_composer::InteractorStyleSwitch::OnLeave ()
+pcl::cloud_composer::InteractorStyleSwitch::OnLeave()
{
- qDebug () << "ON LEAVE";
+ qDebug() << "ON LEAVE";
}
#include <pcl/apps/cloud_composer/point_selectors/manipulation_event.h>
void
-pcl::cloud_composer::ManipulationEvent::addManipulation (const QString& id, const vtkSmartPointer<vtkMatrix4x4>& start, const vtkSmartPointer<vtkMatrix4x4>& end)
+pcl::cloud_composer::ManipulationEvent::addManipulation(
+ const QString& id,
+ const vtkSmartPointer<vtkMatrix4x4>& start,
+ const vtkSmartPointer<vtkMatrix4x4>& end)
{
- id_start_map_.insert (id, start);
- id_end_map_.insert (id, end);
-
+ id_start_map_.insert(id, start);
+ id_end_map_.insert(id, end);
}
#include <QDebug>
-#include <vtkSmartPointer.h>
-#include <vtkIdFilter.h>
-#include <vtkExtractGeometry.h>
-#include <vtkVertexGlyphFilter.h>
-#include <vtkPlanes.h>
#include <vtkAreaPicker.h>
+#include <vtkExtractGeometry.h>
+#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION >= 4)
+#include <vtkGenerateIds.h>
+#else
+#include <vtkIdFilter.h>
+#endif
#include <vtkObjectFactory.h>
+#include <vtkPlanes.h>
+#include <vtkSmartPointer.h>
+#include <vtkVertexGlyphFilter.h>
-namespace pcl
-{
- namespace cloud_composer
- {
- vtkStandardNewMacro(RectangularFrustumSelector);
- }
+namespace pcl {
+namespace cloud_composer {
+vtkStandardNewMacro(RectangularFrustumSelector);
}
+} // namespace pcl
-pcl::cloud_composer::RectangularFrustumSelector::RectangularFrustumSelector ()
+pcl::cloud_composer::RectangularFrustumSelector::RectangularFrustumSelector()
{
selection_complete_event_ = interactor_events::SELECTION_COMPLETE_EVENT;
}
void
-pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp ()
+pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp()
{
-
+
vtkSmartPointer<vtkActor> selected_actor = vtkSmartPointer<vtkActor>::New();
- vtkSmartPointer<vtkDataSetMapper> selected_mapper = vtkSmartPointer<vtkDataSetMapper>::New();
+ vtkSmartPointer<vtkDataSetMapper> selected_mapper =
+ vtkSmartPointer<vtkDataSetMapper>::New();
selected_actor->SetMapper(selected_mapper);
-
- vtkInteractorStyleRubberBandPick::OnLeftButtonUp ();
-
- vtkPlanes* frustum = static_cast<vtkAreaPicker*> (this->GetInteractor ()->GetPicker ())->GetFrustum ();
-
- vtkSmartPointer<vtkIdFilter> id_filter = vtkSmartPointer<vtkIdFilter>::New ();
- id_filter->PointIdsOn ();
-
- vtkSmartPointer<vtkExtractGeometry> extract_geometry = vtkSmartPointer<vtkExtractGeometry>::New ();
- extract_geometry->SetImplicitFunction (frustum);
- extract_geometry->SetInputConnection (id_filter->GetOutputPort ());
-
- vtkSmartPointer<vtkVertexGlyphFilter> glyph_filter = vtkSmartPointer<vtkVertexGlyphFilter>::New ();
- glyph_filter->SetInputConnection (extract_geometry->GetOutputPort ());
-
- vtkSmartPointer<vtkAppendPolyData> append = vtkAppendPolyData::New ();
-
- QMap < QString, vtkPolyData* > id_selected_data_map;
- for (const auto &actor : *actors_)
- {
- const pcl::visualization::CloudActor *act = &actor.second;
- vtkMapper* mapper = act->actor->GetMapper ();
- vtkDataSet* data = mapper->GetInput ();
- vtkPolyData* poly_data = vtkPolyData::SafeDownCast (data);
- id_filter->SetInputData (poly_data);
-
- vtkSmartPointer<vtkPolyData> selected = vtkSmartPointer<vtkPolyData>::New ();
- glyph_filter->SetOutput (selected);
- glyph_filter->Update ();
- if (selected->GetNumberOfPoints() > 0)
- {
- qDebug () << "Selected " << selected->GetNumberOfPoints () << " points.";
- id_selected_data_map.insert ( QString::fromStdString (actor.first), selected);
- append->AddInputData (selected);
- }
+
+ vtkInteractorStyleRubberBandPick::OnLeftButtonUp();
+
+ vtkPlanes* frustum =
+ static_cast<vtkAreaPicker*>(this->GetInteractor()->GetPicker())->GetFrustum();
+
+#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION >= 4)
+ vtkSmartPointer<vtkGenerateIds> id_filter = vtkSmartPointer<vtkGenerateIds>::New();
+#else
+ vtkSmartPointer<vtkIdFilter> id_filter = vtkSmartPointer<vtkIdFilter>::New();
+#endif
+ id_filter->PointIdsOn();
+
+ vtkSmartPointer<vtkExtractGeometry> extract_geometry =
+ vtkSmartPointer<vtkExtractGeometry>::New();
+ extract_geometry->SetImplicitFunction(frustum);
+ extract_geometry->SetInputConnection(id_filter->GetOutputPort());
+
+ vtkSmartPointer<vtkVertexGlyphFilter> glyph_filter =
+ vtkSmartPointer<vtkVertexGlyphFilter>::New();
+ glyph_filter->SetInputConnection(extract_geometry->GetOutputPort());
+
+ vtkSmartPointer<vtkAppendPolyData> append = vtkAppendPolyData::New();
+
+ QMap<QString, vtkPolyData*> id_selected_data_map;
+ for (const auto& actor : *actors_) {
+ const pcl::visualization::CloudActor* act = &actor.second;
+ vtkMapper* mapper = act->actor->GetMapper();
+ vtkDataSet* data = mapper->GetInput();
+ vtkPolyData* poly_data = vtkPolyData::SafeDownCast(data);
+ id_filter->SetInputData(poly_data);
+
+ vtkSmartPointer<vtkPolyData> selected = vtkSmartPointer<vtkPolyData>::New();
+ glyph_filter->SetOutput(selected);
+ glyph_filter->Update();
+ if (selected->GetNumberOfPoints() > 0) {
+ qDebug() << "Selected " << selected->GetNumberOfPoints() << " points.";
+ id_selected_data_map.insert(QString::fromStdString(actor.first), selected);
+ append->AddInputData(selected);
+ }
}
- append->Update ();
- vtkSmartPointer<vtkPolyData> all_points = append->GetOutput ();
- qDebug () << "Allpoints = " <<all_points->GetNumberOfPoints ();
-
- selected_mapper->SetInputData (all_points);
- selected_mapper->ScalarVisibilityOff ();
-
- selected_actor->GetProperty ()->SetColor (0.0, 1.0, 0.0); //(R,G,B)
- selected_actor->GetProperty ()->SetPointSize (3);
-
- this->CurrentRenderer->AddActor (selected_actor);
- this->GetInteractor ()->GetRenderWindow ()->Render ();
- this->HighlightProp (nullptr);
-
- if (all_points->GetNumberOfPoints () > 0)
- {
- SelectionEvent* selected = new SelectionEvent (all_points, selected_actor, selected_mapper, id_selected_data_map, this->CurrentRenderer);
- this->InvokeEvent (this->selection_complete_event_, selected);
+ append->Update();
+ vtkSmartPointer<vtkPolyData> all_points = append->GetOutput();
+ qDebug() << "Allpoints = " << all_points->GetNumberOfPoints();
+
+ selected_mapper->SetInputData(all_points);
+ selected_mapper->ScalarVisibilityOff();
+
+ selected_actor->GetProperty()->SetColor(0.0, 1.0, 0.0); //(R,G,B)
+ selected_actor->GetProperty()->SetPointSize(3);
+
+ this->CurrentRenderer->AddActor(selected_actor);
+ this->GetInteractor()->GetRenderWindow()->Render();
+ this->HighlightProp(nullptr);
+
+ if (all_points->GetNumberOfPoints() > 0) {
+ SelectionEvent* selected = new SelectionEvent(all_points,
+ selected_actor,
+ selected_mapper,
+ id_selected_data_map,
+ this->CurrentRenderer);
+ this->InvokeEvent(this->selection_complete_event_, selected);
}
}
-
#include <QDebug>
#include <QItemSelectionModel>
-#include <vtkSmartPointer.h>
-#include <vtkMatrix4x4.h>
-#include <vtkLODActor.h>
#include <vtkInteractorStyleTrackballActor.h>
+#include <vtkLODActor.h>
+#include <vtkMatrix4x4.h>
+#include <vtkObjectFactory.h>
#include <vtkRenderWindowInteractor.h>
+#include <vtkSmartPointer.h>
#include <vtkTransform.h>
-#include <vtkObjectFactory.h>
-
-namespace pcl
-{
- namespace cloud_composer
- {
- vtkStandardNewMacro(SelectedTrackballStyleInteractor);
- }
+namespace pcl {
+namespace cloud_composer {
+vtkStandardNewMacro(SelectedTrackballStyleInteractor);
}
+} // namespace pcl
-pcl::cloud_composer::SelectedTrackballStyleInteractor::SelectedTrackballStyleInteractor ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::
+ SelectedTrackballStyleInteractor()
{
- manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT;
+ manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT;
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::setSelectedActors ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::setSelectedActors()
{
- QList <QString> selected_cloud_ids;
- QModelIndexList selected_indexes = model_->getSelectionModel()->selectedIndexes ();
- foreach (QModelIndex index, selected_indexes)
- {
- QStandardItem* item = model_->itemFromIndex (index);
- CloudItem* cloud_item = dynamic_cast <CloudItem*> (item);
+ QList<QString> selected_cloud_ids;
+ QModelIndexList selected_indexes = model_->getSelectionModel()->selectedIndexes();
+ foreach (QModelIndex index, selected_indexes) {
+ QStandardItem* item = model_->itemFromIndex(index);
+ CloudItem* cloud_item = dynamic_cast<CloudItem*>(item);
if (cloud_item)
- selected_cloud_ids.append (cloud_item->getId ());
+ selected_cloud_ids.append(cloud_item->getId());
}
-
- for (const auto &actorItem : *actors_)
- {
- QString id = QString::fromStdString (actorItem.first);
- if (selected_cloud_ids.contains (id))
- {
+
+ for (const auto& actorItem : *actors_) {
+ QString id = QString::fromStdString(actorItem.first);
+ if (selected_cloud_ids.contains(id)) {
vtkLODActor* actor = actorItem.second.actor;
- qDebug () << "Adding "<<id<< " to selected manip! ptr ="<<actor;
- selected_actors_map_.insert (id ,actor);
- vtkSmartPointer<vtkMatrix4x4> start_matrix = vtkSmartPointer<vtkMatrix4x4>::New ();
- actor->GetMatrix (start_matrix);
- start_matrix_map_.insert (id,start_matrix);
+ qDebug() << "Adding " << id << " to selected manip! ptr =" << actor;
+ selected_actors_map_.insert(id, actor);
+ vtkSmartPointer<vtkMatrix4x4> start_matrix = vtkSmartPointer<vtkMatrix4x4>::New();
+ actor->GetMatrix(start_matrix);
+ start_matrix_map_.insert(id, start_matrix);
}
}
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::OnLeftButtonDown ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::OnLeftButtonDown()
{
vtkInteractorStyleTrackballActor::OnLeftButtonDown();
-
- setSelectedActors ();
+
+ setSelectedActors();
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::OnRightButtonDown ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::OnRightButtonDown()
{
vtkInteractorStyleTrackballActor::OnRightButtonDown();
-
- setSelectedActors ();
+
+ setSelectedActors();
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::OnLeftButtonUp ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::OnLeftButtonUp()
{
vtkInteractorStyleTrackballActor::OnLeftButtonUp();
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- ManipulationEvent* manip_event = new ManipulationEvent ();
- //Fetch the actor we manipulated
- vtkSmartPointer<vtkMatrix4x4> end_matrix = vtkSmartPointer<vtkMatrix4x4>::New ();
- actor->GetMatrix (end_matrix);
- manip_event->addManipulation (id, start_matrix_map_.value (id), end_matrix);
- this->InvokeEvent (this->manipulation_complete_event_, manip_event);
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ ManipulationEvent* manip_event = new ManipulationEvent();
+ // Fetch the actor we manipulated
+ vtkSmartPointer<vtkMatrix4x4> end_matrix = vtkSmartPointer<vtkMatrix4x4>::New();
+ actor->GetMatrix(end_matrix);
+ manip_event->addManipulation(id, start_matrix_map_.value(id), end_matrix);
+ this->InvokeEvent(this->manipulation_complete_event_, manip_event);
}
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::OnRightButtonUp ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::OnRightButtonUp()
{
vtkInteractorStyleTrackballActor::OnRightButtonUp();
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- ManipulationEvent* manip_event = new ManipulationEvent ();
- //Fetch the actor we manipulated
- vtkSmartPointer<vtkMatrix4x4> end_matrix = vtkSmartPointer<vtkMatrix4x4>::New ();
- actor->GetMatrix (end_matrix);
- manip_event->addManipulation (id, start_matrix_map_.value (id), end_matrix);
- this->InvokeEvent (this->manipulation_complete_event_, manip_event);
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ ManipulationEvent* manip_event = new ManipulationEvent();
+ // Fetch the actor we manipulated
+ vtkSmartPointer<vtkMatrix4x4> end_matrix = vtkSmartPointer<vtkMatrix4x4>::New();
+ actor->GetMatrix(end_matrix);
+ manip_event->addManipulation(id, start_matrix_map_.value(id), end_matrix);
+ this->InvokeEvent(this->manipulation_complete_event_, manip_event);
}
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::Rotate ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::Rotate()
{
- if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr)
- {
+ if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr) {
return;
}
-
- vtkRenderWindowInteractor *rwi = this->Interactor;
- vtkCamera *cam = this->CurrentRenderer->GetActiveCamera();
-
+
+ vtkRenderWindowInteractor* rwi = this->Interactor;
+ vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
+
// First get the origin of the assembly
- double *obj_center = this->InteractionProp->GetCenter();
-
+ double* obj_center = this->InteractionProp->GetCenter();
+
// GetLength gets the length of the diagonal of the bounding box
double boundRadius = this->InteractionProp->GetLength() * 0.5;
-
+
// Get the view up and view right vectors
double view_up[3], view_look[3], view_right[3];
-
+
cam->OrthogonalizeViewUp();
cam->ComputeViewPlaneNormal();
cam->GetViewUp(view_up);
cam->GetViewPlaneNormal(view_look);
vtkMath::Cross(view_up, view_look, view_right);
vtkMath::Normalize(view_right);
-
+
// Get the furtherest point from object position+origin
double outsidept[3];
-
+
outsidept[0] = obj_center[0] + view_right[0] * boundRadius;
outsidept[1] = obj_center[1] + view_right[1] * boundRadius;
outsidept[2] = obj_center[2] + view_right[2] * boundRadius;
-
+
// Convert them to display coord
double disp_obj_center[3];
-
- this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2],
- disp_obj_center);
-
- this->ComputeWorldToDisplay(outsidept[0], outsidept[1], outsidept[2],
- outsidept);
-
- double radius = sqrt(vtkMath::Distance2BetweenPoints(disp_obj_center,
- outsidept));
+
+ this->ComputeWorldToDisplay(
+ obj_center[0], obj_center[1], obj_center[2], disp_obj_center);
+
+ this->ComputeWorldToDisplay(outsidept[0], outsidept[1], outsidept[2], outsidept);
+
+ double radius = sqrt(vtkMath::Distance2BetweenPoints(disp_obj_center, outsidept));
double nxf = (rwi->GetEventPosition()[0] - disp_obj_center[0]) / radius;
-
+
double nyf = (rwi->GetEventPosition()[1] - disp_obj_center[1]) / radius;
-
+
double oxf = (rwi->GetLastEventPosition()[0] - disp_obj_center[0]) / radius;
-
+
double oyf = (rwi->GetLastEventPosition()[1] - disp_obj_center[1]) / radius;
-
- if (((nxf * nxf + nyf * nyf) <= 1.0) &&
- ((oxf * oxf + oyf * oyf) <= 1.0))
- {
- double newXAngle = vtkMath::DegreesFromRadians( asin( nxf ) );
- double newYAngle = vtkMath::DegreesFromRadians( asin( nyf ) );
- double oldXAngle = vtkMath::DegreesFromRadians( asin( oxf ) );
- double oldYAngle = vtkMath::DegreesFromRadians( asin( oyf ) );
-
+
+ if (((nxf * nxf + nyf * nyf) <= 1.0) && ((oxf * oxf + oyf * oyf) <= 1.0)) {
+ double newXAngle = vtkMath::DegreesFromRadians(asin(nxf));
+ double newYAngle = vtkMath::DegreesFromRadians(asin(nyf));
+ double oldXAngle = vtkMath::DegreesFromRadians(asin(oxf));
+ double oldYAngle = vtkMath::DegreesFromRadians(asin(oyf));
+
double scale[3];
scale[0] = scale[1] = scale[2] = 1.0;
-
- double **rotate = new double*[2];
-
+
+ double** rotate = new double*[2];
+
rotate[0] = new double[4];
rotate[1] = new double[4];
-
+
rotate[0][0] = newXAngle - oldXAngle;
rotate[0][1] = view_up[0];
rotate[0][2] = view_up[1];
rotate[0][3] = view_up[2];
-
+
rotate[1][0] = oldYAngle - newYAngle;
rotate[1][1] = view_right[0];
rotate[1][2] = view_right[1];
rotate[1][3] = view_right[2];
-
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- this->Prop3DTransform(actor,
- obj_center,
- 2,
- rotate,
- scale);
+
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ this->Prop3DTransform(actor, obj_center, 2, rotate, scale);
}
- delete [] rotate[0];
- delete [] rotate[1];
- delete [] rotate;
- }
-
- if (this->AutoAdjustCameraClippingRange)
- {
+ delete[] rotate[0];
+ delete[] rotate[1];
+ delete[] rotate;
+ }
+
+ if (this->AutoAdjustCameraClippingRange) {
this->CurrentRenderer->ResetCameraClippingRange();
}
-
- rwi->Render();
+
+ rwi->Render();
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::Spin ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::Spin()
{
- if ( this->CurrentRenderer == nullptr || this->InteractionProp == nullptr )
- {
+ if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr) {
return;
}
-
- vtkRenderWindowInteractor *rwi = this->Interactor;
- vtkCamera *cam = this->CurrentRenderer->GetActiveCamera();
-
+
+ vtkRenderWindowInteractor* rwi = this->Interactor;
+ vtkCamera* cam = this->CurrentRenderer->GetActiveCamera();
+
// Get the axis to rotate around = vector from eye to origin
-
- double *obj_center = this->InteractionProp->GetCenter();
-
+
+ double* obj_center = this->InteractionProp->GetCenter();
+
double motion_vector[3];
double view_point[3];
-
- if (cam->GetParallelProjection())
- {
+
+ if (cam->GetParallelProjection()) {
// If parallel projection, want to get the view plane normal...
cam->ComputeViewPlaneNormal();
- cam->GetViewPlaneNormal( motion_vector );
+ cam->GetViewPlaneNormal(motion_vector);
}
- else
- {
+ else {
// Perspective projection, get vector from eye to center of actor
- cam->GetPosition( view_point );
+ cam->GetPosition(view_point);
motion_vector[0] = view_point[0] - obj_center[0];
motion_vector[1] = view_point[1] - obj_center[1];
motion_vector[2] = view_point[2] - obj_center[2];
vtkMath::Normalize(motion_vector);
}
-
+
double disp_obj_center[3];
-
- this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2],
- disp_obj_center);
-
- double newAngle =
- vtkMath::DegreesFromRadians( std::atan2( rwi->GetEventPosition()[1] - disp_obj_center[1],
- rwi->GetEventPosition()[0] - disp_obj_center[0] ) );
-
- double oldAngle =
- vtkMath::DegreesFromRadians( std::atan2( rwi->GetLastEventPosition()[1] - disp_obj_center[1],
- rwi->GetLastEventPosition()[0] - disp_obj_center[0] ) );
-
+
+ this->ComputeWorldToDisplay(
+ obj_center[0], obj_center[1], obj_center[2], disp_obj_center);
+
+ double newAngle = vtkMath::DegreesFromRadians(
+ std::atan2(rwi->GetEventPosition()[1] - disp_obj_center[1],
+ rwi->GetEventPosition()[0] - disp_obj_center[0]));
+
+ double oldAngle = vtkMath::DegreesFromRadians(
+ std::atan2(rwi->GetLastEventPosition()[1] - disp_obj_center[1],
+ rwi->GetLastEventPosition()[0] - disp_obj_center[0]));
+
double scale[3];
scale[0] = scale[1] = scale[2] = 1.0;
-
- double **rotate = new double*[1];
+
+ double** rotate = new double*[1];
rotate[0] = new double[4];
-
+
rotate[0][0] = newAngle - oldAngle;
rotate[0][1] = motion_vector[0];
rotate[0][2] = motion_vector[1];
rotate[0][3] = motion_vector[2];
-
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- this->Prop3DTransform(actor,
- obj_center,
- 1,
- rotate,
- scale);
+
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ this->Prop3DTransform(actor, obj_center, 1, rotate, scale);
}
-
- delete [] rotate[0];
- delete [] rotate;
-
- if ( this->AutoAdjustCameraClippingRange )
- {
+
+ delete[] rotate[0];
+ delete[] rotate;
+
+ if (this->AutoAdjustCameraClippingRange) {
this->CurrentRenderer->ResetCameraClippingRange();
}
-
+
rwi->Render();
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::Pan ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::Pan()
{
- if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr)
- {
+ if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr) {
return;
}
-
- vtkRenderWindowInteractor *rwi = this->Interactor;
-
+
+ vtkRenderWindowInteractor* rwi = this->Interactor;
+
// Use initial center as the origin from which to pan
-
- double *obj_center = this->InteractionProp->GetCenter();
-
+
+ double* obj_center = this->InteractionProp->GetCenter();
+
double disp_obj_center[3], new_pick_point[4];
double old_pick_point[4], motion_vector[3];
-
- this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2],
- disp_obj_center);
-
- this->ComputeDisplayToWorld(rwi->GetEventPosition()[0],
- rwi->GetEventPosition()[1],
+
+ this->ComputeWorldToDisplay(
+ obj_center[0], obj_center[1], obj_center[2], disp_obj_center);
+
+ this->ComputeDisplayToWorld(rwi->GetEventPosition()[0],
+ rwi->GetEventPosition()[1],
disp_obj_center[2],
new_pick_point);
-
- this->ComputeDisplayToWorld(rwi->GetLastEventPosition()[0],
- rwi->GetLastEventPosition()[1],
+
+ this->ComputeDisplayToWorld(rwi->GetLastEventPosition()[0],
+ rwi->GetLastEventPosition()[1],
disp_obj_center[2],
old_pick_point);
-
+
motion_vector[0] = new_pick_point[0] - old_pick_point[0];
motion_vector[1] = new_pick_point[1] - old_pick_point[1];
motion_vector[2] = new_pick_point[2] - old_pick_point[2];
-
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- if (actor->GetUserMatrix() != nullptr)
- {
- vtkTransform *t = vtkTransform::New();
+
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ if (actor->GetUserMatrix() != nullptr) {
+ vtkTransform* t = vtkTransform::New();
t->PostMultiply();
t->SetMatrix(actor->GetUserMatrix());
t->Translate(motion_vector[0], motion_vector[1], motion_vector[2]);
actor->GetUserMatrix()->DeepCopy(t->GetMatrix());
t->Delete();
}
- else
- {
- actor->AddPosition(motion_vector[0],
- motion_vector[1],
- motion_vector[2]);
+ else {
+ actor->AddPosition(motion_vector[0], motion_vector[1], motion_vector[2]);
}
}
-
-
- if (this->AutoAdjustCameraClippingRange)
- {
+
+ if (this->AutoAdjustCameraClippingRange) {
this->CurrentRenderer->ResetCameraClippingRange();
}
-
+
rwi->Render();
}
void
-pcl::cloud_composer::SelectedTrackballStyleInteractor::UniformScale ()
+pcl::cloud_composer::SelectedTrackballStyleInteractor::UniformScale()
{
- if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr)
- {
+ if (this->CurrentRenderer == nullptr || this->InteractionProp == nullptr) {
return;
}
-
- vtkRenderWindowInteractor *rwi = this->Interactor;
-
+
+ vtkRenderWindowInteractor* rwi = this->Interactor;
+
int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
-
- double *obj_center = this->InteractionProp->GetCenter();
- double *center = this->CurrentRenderer->GetCenter();
-
+
+ double* obj_center = this->InteractionProp->GetCenter();
+ double* center = this->CurrentRenderer->GetCenter();
+
double yf = dy / center[1] * this->MotionFactor;
double scaleFactor = pow(1.1, yf);
-
- double **rotate = nullptr;
-
+
+ double** rotate = nullptr;
+
double scale[3];
scale[0] = scale[1] = scale[2] = scaleFactor;
- foreach (QString id, selected_actors_map_.keys ())
- {
- vtkLODActor* actor = selected_actors_map_.value (id);
- this->Prop3DTransform(actor,
- obj_center,
- 0,
- rotate,
- scale);
+ foreach (QString id, selected_actors_map_.keys()) {
+ vtkLODActor* actor = selected_actors_map_.value(id);
+ this->Prop3DTransform(actor, obj_center, 0, rotate, scale);
}
-
- if (this->AutoAdjustCameraClippingRange)
- {
+
+ if (this->AutoAdjustCameraClippingRange) {
this->CurrentRenderer->ResetCameraClippingRange();
}
-
+
rwi->Render();
}
#include <pcl/apps/cloud_composer/point_selectors/selection_event.h>
-
#include <pcl/point_types.h>
-pcl::cloud_composer::SelectionEvent::~SelectionEvent ()
+pcl::cloud_composer::SelectionEvent::~SelectionEvent()
{
- renderer_->RemoveActor (selected_actor_);
+ renderer_->RemoveActor(selected_actor_);
}
-
void
-pcl::cloud_composer::SelectionEvent::findIndicesInItem (CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices)
+pcl::cloud_composer::SelectionEvent::findIndicesInItem(
+ CloudItem* cloud_item, const pcl::PointIndices::Ptr& indices)
{
// WE DON'T NEED TO DO THIS SEARCH BECAUSE WE HAVE A 1-1 CORRESPONDENCE VTK TO PCL
// THIS IS ONLY THE CASE FOR CLOUDS WITH NO NANs
- //Go through every point in the selected data set and find the matching index in this cloud
- //pcl::search::KdTree<pcl::PointXYZ>::Ptr search = cloud_item->data (KD_TREE_SEARCH).value <pcl::search::Search<pcl::PointXYZ>::Ptr> ();
- // double dblpts[3];
- // PointXYZ pt;
- // std::vector<int> indices;
- // std::vector<float> distances;
+ // Go through every point in the selected data set and find the matching index in this
+ // cloud pcl::search::KdTree<pcl::PointXYZ>::Ptr search = cloud_item->data
+ // (KD_TREE_SEARCH).value <pcl::search::Search<pcl::PointXYZ>::Ptr> ();
+ // double dblpts[3];
+ // PointXYZ pt;
+ // std::vector<int> indices;
+ // std::vector<float> distances;
/*for (int i = 0; i < points->GetNumberOfPoints (); ++i)
{
points->GetPoint(i, dblpts);
if (idx < indices.size ())
{
used_indices.append (indices[idx]);
- id_list.append (indices[idx]);
+ id_list.append (indices[idx]);
}
else
- qCritical () << "More found points in selection than are possible from cloud items!";
+ qCritical () << "More found points in selection than are possible from cloud
+ items!";
}
-
+
}*/
- if (id_selected_data_map_.contains (cloud_item->getId ()))
- {
- vtkPolyData* points_in_item = id_selected_data_map_.value (cloud_item->getId ());
- vtkIdTypeArray* point_ids = vtkIdTypeArray::SafeDownCast(points_in_item->GetPointData ()->GetArray ("vtkIdFilter_Ids"));
-
- indices->indices.resize (point_ids->GetNumberOfTuples ());
- for(vtkIdType i =0; i < point_ids->GetNumberOfTuples (); ++i)
- {
- //qDebug () << "id="<<point_ids->GetValue (i);
- indices->indices[i] = point_ids->GetValue (i);
+ if (id_selected_data_map_.contains(cloud_item->getId())) {
+ vtkPolyData* points_in_item = id_selected_data_map_.value(cloud_item->getId());
+ vtkIdTypeArray* point_ids = vtkIdTypeArray::SafeDownCast(
+ points_in_item->GetPointData()->GetArray("vtkIdFilter_Ids"));
+
+ indices->indices.resize(point_ids->GetNumberOfTuples());
+ for (vtkIdType i = 0; i < point_ids->GetNumberOfTuples(); ++i) {
+ // qDebug () << "id="<<point_ids->GetValue (i);
+ indices->indices[i] = point_ids->GetValue(i);
}
- //qDebug () << points_in_item->GetNumberOfPoints () << " selected points in "<<cloud_item->getId ();
+ // qDebug () << points_in_item->GetNumberOfPoints () << " selected points in
+ // "<<cloud_item->getId ();
}
-
}
-#include <pcl/apps/cloud_composer/properties_model.h>
#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
+#include <pcl/apps/cloud_composer/properties_model.h>
#include <QDebug>
-pcl::cloud_composer::PropertiesModel::PropertiesModel (QObject* parent)
- : QStandardItemModel (parent)
+pcl::cloud_composer::PropertiesModel::PropertiesModel(QObject* parent)
+: QStandardItemModel(parent)
{
- setHorizontalHeaderItem (0, new QStandardItem ("Name"));
- setHorizontalHeaderItem (1, new QStandardItem ("Value"));
+ setHorizontalHeaderItem(0, new QStandardItem("Name"));
+ setHorizontalHeaderItem(1, new QStandardItem("Value"));
}
-pcl::cloud_composer::PropertiesModel::PropertiesModel (CloudComposerItem* parent_item, QObject* parent)
- : QStandardItemModel (parent)
- , parent_item_ (parent_item)
+pcl::cloud_composer::PropertiesModel::PropertiesModel(CloudComposerItem* parent_item,
+ QObject* parent)
+: QStandardItemModel(parent), parent_item_(parent_item)
{
- setHorizontalHeaderItem (0, new QStandardItem ("Name"));
- setHorizontalHeaderItem (1, new QStandardItem ("Value"));
-
- connect (this, SIGNAL (itemChanged (QStandardItem*)),
- this, SLOT (propertyChanged (QStandardItem*)));
+ setHorizontalHeaderItem(0, new QStandardItem("Name"));
+ setHorizontalHeaderItem(1, new QStandardItem("Value"));
+
+ connect(this,
+ SIGNAL(itemChanged(QStandardItem*)),
+ this,
+ SLOT(propertyChanged(QStandardItem*)));
}
-pcl::cloud_composer::PropertiesModel::PropertiesModel (const PropertiesModel& to_copy)
-: QStandardItemModel ()
+pcl::cloud_composer::PropertiesModel::PropertiesModel(const PropertiesModel& to_copy)
+: QStandardItemModel()
{
- for (int i=0; i < to_copy.rowCount (); ++i){
- QList <QStandardItem*> new_row;
- QStandardItem* parent = to_copy.item(i,0);
- QModelIndex parent_index = to_copy.index(i,0);
- new_row.append (parent->clone ());
- for (int j=0; j < to_copy.columnCount (parent_index); ++j)
- {
- if (to_copy.item (i,j))
- new_row.append (to_copy.item(i,j)->clone ());
+ for (int i = 0; i < to_copy.rowCount(); ++i) {
+ QList<QStandardItem*> new_row;
+ QStandardItem* parent = to_copy.item(i, 0);
+ QModelIndex parent_index = to_copy.index(i, 0);
+ new_row.append(parent->clone());
+ for (int j = 0; j < to_copy.columnCount(parent_index); ++j) {
+ if (to_copy.item(i, j))
+ new_row.append(to_copy.item(i, j)->clone());
}
- appendRow (new_row);
+ appendRow(new_row);
}
}
void
-pcl::cloud_composer::PropertiesModel::addProperty (const QString& prop_name, const QVariant& value, Qt::ItemFlags flags, const QString& category)
+pcl::cloud_composer::PropertiesModel::addProperty(const QString& prop_name,
+ const QVariant& value,
+ Qt::ItemFlags flags,
+ const QString& category)
{
- QStandardItem* parent_item = invisibleRootItem ();
- if (category.size () > 0)
- {
- QList<QStandardItem*> items = findItems (category);
- if (items.empty ())
- qWarning () << "No category named "<<prop_name<<" found in "<<parent_item_->text ()<<" adding to root";
- else if (items.size () > 1)
- qCritical () << "Multiple categories with same name found!! This is not good...";
+ QStandardItem* parent_item = invisibleRootItem();
+ if (category.size() > 0) {
+ QList<QStandardItem*> items = findItems(category);
+ if (items.empty())
+ qWarning() << "No category named " << prop_name << " found in "
+ << parent_item_->text() << " adding to root";
+ else if (items.size() > 1)
+ qCritical() << "Multiple categories with same name found!! This is not good...";
else
- parent_item = items.at (0);
+ parent_item = items.at(0);
}
- QList <QStandardItem*> new_row;
- QStandardItem* new_property = new QStandardItem (prop_name);
- new_property->setFlags (Qt::ItemIsSelectable);
- new_row.append (new_property);
-
- QStandardItem* new_value = new QStandardItem ();
- new_value->setFlags (flags);
- new_value->setData (value, Qt::EditRole);
- new_row.append (new_value);
-
- parent_item->appendRow (new_row);
+ QList<QStandardItem*> new_row;
+ QStandardItem* new_property = new QStandardItem(prop_name);
+ new_property->setFlags(Qt::ItemIsSelectable);
+ new_row.append(new_property);
+
+ QStandardItem* new_value = new QStandardItem();
+ new_value->setFlags(flags);
+ new_value->setData(value, Qt::EditRole);
+ new_row.append(new_value);
+
+ parent_item->appendRow(new_row);
}
void
-pcl::cloud_composer::PropertiesModel::addCategory (const QString& category_name)
+pcl::cloud_composer::PropertiesModel::addCategory(const QString& category_name)
{
- QStandardItem* new_category = new QStandardItem (category_name);
- appendRow (new_category);
+ QStandardItem* new_category = new QStandardItem(category_name);
+ appendRow(new_category);
}
-QVariant
-pcl::cloud_composer::PropertiesModel::getProperty (const QString& prop_name) const
+QVariant
+pcl::cloud_composer::PropertiesModel::getProperty(const QString& prop_name) const
{
- //qDebug () << "Searching for property " << prop_name;
- QList<QStandardItem*> items = findItems (prop_name, Qt::MatchExactly | Qt::MatchRecursive, 0);
- if (items.empty ())
- {
- qWarning () << "No property named "<<prop_name<<" found in "<<parent_item_->text ();
- return QVariant ();
+ // qDebug () << "Searching for property " << prop_name;
+ QList<QStandardItem*> items =
+ findItems(prop_name, Qt::MatchExactly | Qt::MatchRecursive, 0);
+ if (items.empty()) {
+ qWarning() << "No property named " << prop_name << " found in "
+ << parent_item_->text();
+ return QVariant();
}
- if (items.size () > 1)
- {
- qWarning () << "Multiple properties found with name "<<prop_name<<" in "<<parent_item_->text ();
+ if (items.size() > 1) {
+ qWarning() << "Multiple properties found with name " << prop_name << " in "
+ << parent_item_->text();
}
- // qDebug () << "Found properties size ="<<items.size ();
-
- QStandardItem* property = items.value (0);
- // qDebug () << "Prop name="<<prop_name<<" row="<<property->row ()<<" col="<<property->column();
- int row = property->row ();
- QStandardItem* parent_item = property->parent ();
+ // qDebug () << "Found properties size ="<<items.size ();
+
+ QStandardItem* property = items.value(0);
+ // qDebug () << "Prop name="<<prop_name<<" row="<<property->row ()<<"
+ // col="<<property->column();
+ int row = property->row();
+ QStandardItem* parent_item = property->parent();
if (parent_item == nullptr)
- parent_item = invisibleRootItem ();
- return parent_item->child (row,1)->data (Qt::EditRole);
+ parent_item = invisibleRootItem();
+ return parent_item->child(row, 1)->data(Qt::EditRole);
}
void
-pcl::cloud_composer::PropertiesModel::copyProperties (const PropertiesModel* to_copy)
+pcl::cloud_composer::PropertiesModel::copyProperties(const PropertiesModel* to_copy)
{
- for (int i=0; i < to_copy->rowCount (); ++i){
- QList <QStandardItem*> new_row;
- QStandardItem* parent = to_copy->item(i,0);
- qDebug () << "Copying "<<parent->text()<< " cols ="<<to_copy->columnCount ();
- new_row.append (parent->clone ());
- for (int j=1; j < to_copy->columnCount (); ++j)
- {
- if (to_copy->item (i,j))
- {
- new_row.append (to_copy->item(i,j)->clone ());
+ for (int i = 0; i < to_copy->rowCount(); ++i) {
+ QList<QStandardItem*> new_row;
+ QStandardItem* parent = to_copy->item(i, 0);
+ qDebug() << "Copying " << parent->text() << " cols =" << to_copy->columnCount();
+ new_row.append(parent->clone());
+ for (int j = 1; j < to_copy->columnCount(); ++j) {
+ if (to_copy->item(i, j)) {
+ new_row.append(to_copy->item(i, j)->clone());
}
}
- appendRow (new_row);
+ appendRow(new_row);
}
}
-
void
-pcl::cloud_composer::PropertiesModel::propertyChanged (QStandardItem*)
+pcl::cloud_composer::PropertiesModel::propertyChanged(QStandardItem*)
{
- //qDebug () << "Property Changed in properties model";
- parent_item_->propertyChanged ();
+ // qDebug () << "Property Changed in properties model";
+ parent_item_->propertyChanged();
}
-#include <pcl/apps/cloud_composer/signal_multiplexer.h>
#include <pcl/apps/cloud_composer/project_model.h>
+#include <pcl/apps/cloud_composer/signal_multiplexer.h>
-pcl::cloud_composer::SignalMultiplexer::SignalMultiplexer (QObject* parent)
- : QObject (parent)
-{
-
-}
-
+pcl::cloud_composer::SignalMultiplexer::SignalMultiplexer(QObject* parent)
+: QObject(parent)
+{}
void
-pcl::cloud_composer::SignalMultiplexer::connect (QObject* sender, const char* signal, const char* slot)
+pcl::cloud_composer::SignalMultiplexer::connect(QObject* sender,
+ const char* signal,
+ const char* slot)
{
Connection conn;
conn.sender = sender;
conn.slot = slot;
connections << conn;
- connect (conn);
+ connect(conn);
}
-
void
-pcl::cloud_composer::SignalMultiplexer::connect (const char* signal, QObject* receiver, const char* slot)
+pcl::cloud_composer::SignalMultiplexer::connect(const char* signal,
+ QObject* receiver,
+ const char* slot)
{
Connection conn;
conn.receiver = receiver;
conn.slot = slot;
connections << conn;
- connect (conn);
+ connect(conn);
}
-
bool
-pcl::cloud_composer::SignalMultiplexer::disconnect (QObject* sender, const char* signal, const char* slot)
+pcl::cloud_composer::SignalMultiplexer::disconnect(QObject* sender,
+ const char* signal,
+ const char* slot)
{
- QMutableListIterator<Connection> it (connections);
- while (it.hasNext ())
- {
+ QMutableListIterator<Connection> it(connections);
+ while (it.hasNext()) {
Connection conn = it.next();
- if ( (QObject*) conn.sender == sender &&
- qstrcmp (conn.signal, signal) == 0 && qstrcmp (conn.slot, slot) == 0)
- {
- disconnect (conn);
+ if ((QObject*)conn.sender == sender && qstrcmp(conn.signal, signal) == 0 &&
+ qstrcmp(conn.slot, slot) == 0) {
+ disconnect(conn);
it.remove();
return true;
}
return false;
}
-
bool
-pcl::cloud_composer::SignalMultiplexer::disconnect (const char* signal, QObject* receiver, const char* slot)
+pcl::cloud_composer::SignalMultiplexer::disconnect(const char* signal,
+ QObject* receiver,
+ const char* slot)
{
- QMutableListIterator<Connection> it (connections);
- while (it.hasNext ())
- {
+ QMutableListIterator<Connection> it(connections);
+ while (it.hasNext()) {
Connection conn = it.next();
- if ( (QObject*) conn.receiver == receiver &&
- qstrcmp (conn.signal, signal) == 0 && qstrcmp (conn.slot, slot) == 0)
- {
- disconnect (conn);
+ if ((QObject*)conn.receiver == receiver && qstrcmp(conn.signal, signal) == 0 &&
+ qstrcmp(conn.slot, slot) == 0) {
+ disconnect(conn);
it.remove();
return true;
}
return false;
}
-
void
-pcl::cloud_composer::SignalMultiplexer::connect (const Connection& conn)
+pcl::cloud_composer::SignalMultiplexer::connect(const Connection& conn)
{
if (!object)
return;
return;
if (conn.sender)
- QObject::connect ( (QObject*) conn.sender, conn.signal, (QObject*) object, conn.slot);
+ QObject::connect((QObject*)conn.sender, conn.signal, (QObject*)object, conn.slot);
else
- QObject::connect ( (QObject*) object, conn.signal, (QObject*) conn.receiver, conn.slot);
+ QObject::connect((QObject*)object, conn.signal, (QObject*)conn.receiver, conn.slot);
}
-
-void
-pcl::cloud_composer::SignalMultiplexer::disconnect (const Connection& conn)
+void
+pcl::cloud_composer::SignalMultiplexer::disconnect(const Connection& conn)
{
if (!object)
return;
return;
if (conn.sender)
- QObject::disconnect ( (QObject*) conn.sender, conn.signal, (QObject*) object, conn.slot);
+ QObject::disconnect(
+ (QObject*)conn.sender, conn.signal, (QObject*)object, conn.slot);
else
- QObject::disconnect ( (QObject*) object, conn.signal, (QObject*) conn.receiver, conn.slot);
-
+ QObject::disconnect(
+ (QObject*)object, conn.signal, (QObject*)conn.receiver, conn.slot);
}
-
-void
-pcl::cloud_composer::SignalMultiplexer::setCurrentObject (QObject* newObject)
+void
+pcl::cloud_composer::SignalMultiplexer::setCurrentObject(QObject* newObject)
{
if (newObject == object)
return;
- for (const auto &connection : connections)
- disconnect (connection);
+ for (const auto& connection : connections)
+ disconnect(connection);
object = newObject;
- for (const auto &connection : connections)
- connect (connection);
+ for (const auto& connection : connections)
+ connect(connection);
- ProjectModel* model = dynamic_cast<ProjectModel*> (newObject);
+ ProjectModel* model = dynamic_cast<ProjectModel*>(newObject);
if (model)
- model->emitAllStateSignals ();
-
- //let the world know about who's on top now
- emit currentObjectChanged (object);
+ model->emitAllStateSignals();
+
+ // let the world know about who's on top now
+ emit currentObjectChanged(object);
}
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
-pcl::cloud_composer::AbstractTool::AbstractTool (PropertiesModel* parameter_model, QObject* parent)
- : QObject (parent)
-
+pcl::cloud_composer::AbstractTool::AbstractTool(PropertiesModel* parameter_model,
+ QObject* parent)
+: QObject(parent)
+
{
- parameter_model_ = new PropertiesModel (this);
- //If there's a model copy it into the local copy
- if (parameter_model)
- {
+ parameter_model_ = new PropertiesModel(this);
+ // If there's a model copy it into the local copy
+ if (parameter_model) {
parameter_model_->copyProperties(parameter_model);
-
}
-
-
}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::AbstractTool::performAction (QList <const CloudComposerItem*>, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::AbstractTool::performAction(QList<const CloudComposerItem*>,
+ PointTypeFlags::PointType)
{
- qDebug () << "AbstractTool::performTemplatedAction";
- return QList <CloudComposerItem*> ();
+ qDebug() << "AbstractTool::performTemplatedAction";
+ return QList<CloudComposerItem*>();
}
-#include <pcl/apps/cloud_composer/toolbox_model.h>
+#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
+#include <pcl/apps/cloud_composer/project_model.h>
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
#include <pcl/apps/cloud_composer/tool_interface/tool_factory.h>
-#include <pcl/apps/cloud_composer/project_model.h>
-#include <pcl/apps/cloud_composer/items/cloud_composer_item.h>
+#include <pcl/apps/cloud_composer/toolbox_model.h>
#include <QMessageBox>
#include <QTreeView>
-pcl::cloud_composer::ToolBoxModel::ToolBoxModel (QTreeView* tool_view, QTreeView* parameter_view_, QObject* parent)
-: QStandardItemModel (parent)
-, tool_view_ (tool_view)
-, parameter_view_ (parameter_view_)
-, project_model_ (nullptr)
-{
-
-}
+pcl::cloud_composer::ToolBoxModel::ToolBoxModel(QTreeView* tool_view,
+ QTreeView* parameter_view_,
+ QObject* parent)
+: QStandardItemModel(parent)
+, tool_view_(tool_view)
+, parameter_view_(parameter_view_)
+, project_model_(nullptr)
+{}
-pcl::cloud_composer::ToolBoxModel::ToolBoxModel (const ToolBoxModel&)
-: QStandardItemModel ()
-{
-}
+pcl::cloud_composer::ToolBoxModel::ToolBoxModel(const ToolBoxModel&)
+: QStandardItemModel()
+{}
void
-pcl::cloud_composer::ToolBoxModel::addTool (ToolFactory* tool_factory)
+pcl::cloud_composer::ToolBoxModel::addTool(ToolFactory* tool_factory)
{
- //qDebug () << "Icon name:"<< tool_factory->getIconName ();
- QIcon new_tool_icon = QIcon (tool_factory->getIconName ());
- QStandardItem* new_tool_item = new QStandardItem (new_tool_icon, tool_factory->getPluginName ());
- new_tool_item->setEditable (false);
-
- new_tool_item->setData (QVariant::fromValue (tool_factory), FACTORY);
- PropertiesModel* new_tool_parameters= tool_factory->createToolParameterModel (this);
- new_tool_item->setData (QVariant::fromValue (new_tool_parameters), PARAMETER_MODEL);
-
- tool_items.insert (new_tool_item);
- QStandardItem* group_item = addToolGroup (tool_factory->getToolGroupName ());
- group_item->appendRow (new_tool_item);
- //Expand the view for this tool group
+ // qDebug () << "Icon name:"<< tool_factory->getIconName ();
+ QIcon new_tool_icon = QIcon(tool_factory->getIconName());
+ QStandardItem* new_tool_item =
+ new QStandardItem(new_tool_icon, tool_factory->getPluginName());
+ new_tool_item->setEditable(false);
+
+ new_tool_item->setData(QVariant::fromValue(tool_factory), FACTORY);
+ PropertiesModel* new_tool_parameters = tool_factory->createToolParameterModel(this);
+ new_tool_item->setData(QVariant::fromValue(new_tool_parameters), PARAMETER_MODEL);
+
+ tool_items.insert(new_tool_item);
+ QStandardItem* group_item = addToolGroup(tool_factory->getToolGroupName());
+ group_item->appendRow(new_tool_item);
+ // Expand the view for this tool group
QModelIndex group_index = this->indexFromItem(group_item);
- tool_view_->setExpanded (group_index, true);
+ tool_view_->setExpanded(group_index, true);
}
void
-pcl::cloud_composer::ToolBoxModel::setSelectionModel (QItemSelectionModel* selection_model)
+pcl::cloud_composer::ToolBoxModel::setSelectionModel(
+ QItemSelectionModel* selection_model)
{
selection_model_ = selection_model;
}
-
+
QStandardItem*
-pcl::cloud_composer::ToolBoxModel::addToolGroup (const QString& tool_group_name)
+pcl::cloud_composer::ToolBoxModel::addToolGroup(const QString& tool_group_name)
{
- QList <QStandardItem*> matches_name = findItems (tool_group_name);
- if (matches_name.empty ())
- {
- QStandardItem* new_group_item = new QStandardItem (tool_group_name);
- appendRow (new_group_item);
- new_group_item->setSelectable (false);
- new_group_item->setEditable (false);
+ QList<QStandardItem*> matches_name = findItems(tool_group_name);
+ if (matches_name.empty()) {
+ QStandardItem* new_group_item = new QStandardItem(tool_group_name);
+ appendRow(new_group_item);
+ new_group_item->setSelectable(false);
+ new_group_item->setEditable(false);
return new_group_item;
}
- if (matches_name.size () > 1)
- {
- qWarning () << "Multiple tool groups with same name in ToolBoxModel!!";
+ if (matches_name.size() > 1) {
+ qWarning() << "Multiple tool groups with same name in ToolBoxModel!!";
}
-
- return matches_name.value (0);
-
+
+ return matches_name.value(0);
}
-void
-pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model, ProjectModel*)
+void
+pcl::cloud_composer::ToolBoxModel::activeProjectChanged(ProjectModel* new_model,
+ ProjectModel*)
{
- //Disconnect old project model signal for selection change
- if (project_model_)
- {
- disconnect (project_model_->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)),
- this, SLOT (selectedItemChanged (QItemSelection,QItemSelection)));
- disconnect (project_model_, SIGNAL (modelChanged()),
- this, SLOT (modelChanged()));
-
- }
- qDebug () << "Active project changed in ToolBox Model!";
- project_model_ = new_model;
-
- //Update enabled tools, make connection for doing this automatically
- if (project_model_)
- {
- updateEnabledTools (project_model_->getSelectionModel ()->selection ());
- connect (project_model_->getSelectionModel (), SIGNAL (selectionChanged (QItemSelection,QItemSelection)),
- this, SLOT (selectedItemChanged (QItemSelection,QItemSelection)));
- connect (project_model_, SIGNAL (modelChanged()),
- this, SLOT (modelChanged()));
+ // Disconnect old project model signal for selection change
+ if (project_model_) {
+ disconnect(project_model_->getSelectionModel(),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this,
+ SLOT(selectedItemChanged(QItemSelection, QItemSelection)));
+ disconnect(project_model_, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
}
+ qDebug() << "Active project changed in ToolBox Model!";
+ project_model_ = new_model;
+ // Update enabled tools, make connection for doing this automatically
+ if (project_model_) {
+ updateEnabledTools(project_model_->getSelectionModel()->selection());
+ connect(project_model_->getSelectionModel(),
+ SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this,
+ SLOT(selectedItemChanged(QItemSelection, QItemSelection)));
+ connect(project_model_, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
+ }
}
void
-pcl::cloud_composer::ToolBoxModel::selectedToolChanged (const QModelIndex & current, const QModelIndex &)
+pcl::cloud_composer::ToolBoxModel::selectedToolChanged(const QModelIndex& current,
+ const QModelIndex&)
{
- //qDebug() << "Selected Tool changed";
- if (!parameter_view_)
- {
- qCritical () << "Toolbox parameter view not set!!!";
+ // qDebug() << "Selected Tool changed";
+ if (!parameter_view_) {
+ qCritical() << "Toolbox parameter view not set!!!";
return;
- }
- QVariant parameter_model = current.data (PARAMETER_MODEL);
- parameter_view_->setModel ( parameter_model.value <PropertiesModel*> ());
- parameter_view_->expandAll ();
+ }
+ QVariant parameter_model = current.data(PARAMETER_MODEL);
+ parameter_view_->setModel(parameter_model.value<PropertiesModel*>());
+ parameter_view_->expandAll();
}
-
void
-pcl::cloud_composer::ToolBoxModel::toolAction ()
+pcl::cloud_composer::ToolBoxModel::toolAction()
{
- QModelIndex current_index = selection_model_->currentIndex ();
- if (!current_index.isValid ())
- {
- QMessageBox::warning (qobject_cast<QWidget *>(this->parent ()), "No Tool Selected", "Cannot execute action, no tool selected!");
+ QModelIndex current_index = selection_model_->currentIndex();
+ if (!current_index.isValid()) {
+ QMessageBox::warning(qobject_cast<QWidget*>(this->parent()),
+ "No Tool Selected",
+ "Cannot execute action, no tool selected!");
return;
}
- ToolFactory* tool_factory = (current_index.data (FACTORY)).value <ToolFactory*> ();
- PropertiesModel* parameter_model = (current_index.data (PARAMETER_MODEL)).value <PropertiesModel*> ();
+ ToolFactory* tool_factory = (current_index.data(FACTORY)).value<ToolFactory*>();
+ PropertiesModel* parameter_model =
+ (current_index.data(PARAMETER_MODEL)).value<PropertiesModel*>();
//
- AbstractTool* tool = tool_factory->createTool (parameter_model);
-
- emit enqueueToolAction (tool);
+ AbstractTool* tool = tool_factory->createTool(parameter_model);
+
+ emit enqueueToolAction(tool);
}
-void
-pcl::cloud_composer::ToolBoxModel::selectedItemChanged ( const QItemSelection & selected, const QItemSelection &)
+void
+pcl::cloud_composer::ToolBoxModel::selectedItemChanged(const QItemSelection& selected,
+ const QItemSelection&)
{
- updateEnabledTools (selected);
+ updateEnabledTools(selected);
}
-void
-pcl::cloud_composer::ToolBoxModel::enableAllTools ()
+void
+pcl::cloud_composer::ToolBoxModel::enableAllTools()
{
- foreach (QStandardItem* tool, tool_items)
- {
- tool->setEnabled (true);
+ foreach (QStandardItem* tool, tool_items) {
+ tool->setEnabled(true);
}
}
void
-pcl::cloud_composer::ToolBoxModel::modelChanged ()
+pcl::cloud_composer::ToolBoxModel::modelChanged()
{
- updateEnabledTools (project_model_->getSelectionModel ()->selection ());
+ updateEnabledTools(project_model_->getSelectionModel()->selection());
}
void
-pcl::cloud_composer::ToolBoxModel::updateEnabledTools (const QItemSelection& current_selection)
+pcl::cloud_composer::ToolBoxModel::updateEnabledTools(
+ const QItemSelection& current_selection)
{
- //qDebug () << "UPDATING ENABLED TOOLS!";
- QModelIndexList current_indices = current_selection.indexes ();
- QMultiMap < int, QStandardItem* > type_items_map;
- foreach (QModelIndex current, current_indices)
- {
- if (current.isValid ())
- {
- QStandardItem* current_item = project_model_->itemFromIndex (current);
- type_items_map.insert (current_item->type (), current_item);
+ // qDebug () << "UPDATING ENABLED TOOLS!";
+ QModelIndexList current_indices = current_selection.indexes();
+ QMultiMap<int, QStandardItem*> type_items_map;
+ foreach (QModelIndex current, current_indices) {
+ if (current.isValid()) {
+ QStandardItem* current_item = project_model_->itemFromIndex(current);
+ type_items_map.insert(current_item->type(), current_item);
}
}
- enableAllTools ();
- QList <QStandardItem*> enabled_tools = tool_items.values ();
- QMap <QStandardItem*,QString> disabled_tools;
+ enableAllTools();
+ QList<QStandardItem*> enabled_tools = tool_items.values();
+ QMap<QStandardItem*, QString> disabled_tools;
QMutableListIterator<QStandardItem*> enabled_itr(enabled_tools);
- //Go through tools, removing from enabled list if they fail to pass tests
- while (enabled_itr.hasNext())
- {
- QStandardItem* tool_item = enabled_itr.next ();
- ToolFactory* tool_factory = (tool_item->data (FACTORY)).value <ToolFactory*> ();
- CloudComposerItem::ItemType input_type = tool_factory->getInputItemType ();
- QList <CloudComposerItem::ItemType> required_children_types = tool_factory->getRequiredInputChildrenTypes();
- //Check if enough items for tool are selected
- if ( tool_factory-> getNumInputItems() > current_indices.size() )
- {
- enabled_itr.remove ();
- disabled_tools.insert (tool_item, tr("Tool Requires %1 Items (%2 Selected)").arg(tool_factory-> getNumInputItems()).arg(current_indices.size ()));
+ // Go through tools, removing from enabled list if they fail to pass tests
+ while (enabled_itr.hasNext()) {
+ QStandardItem* tool_item = enabled_itr.next();
+ ToolFactory* tool_factory = (tool_item->data(FACTORY)).value<ToolFactory*>();
+ CloudComposerItem::ItemType input_type = tool_factory->getInputItemType();
+ QList<CloudComposerItem::ItemType> required_children_types =
+ tool_factory->getRequiredInputChildrenTypes();
+ // Check if enough items for tool are selected
+ if (tool_factory->getNumInputItems() > current_indices.size()) {
+ enabled_itr.remove();
+ disabled_tools.insert(tool_item,
+ tr("Tool Requires %1 Items (%2 Selected)")
+ .arg(tool_factory->getNumInputItems())
+ .arg(current_indices.size()));
}
- //Check if selection includes at least one item with correct input type
- else if ( ! type_items_map.keys ().contains (input_type))
- {
- enabled_itr.remove ();
- disabled_tools.insert (tool_item, tr("Tool Requires item type %1 selected").arg (ITEM_TYPES_STRINGS.value (input_type - CloudComposerItem::CLOUD_COMPOSER_ITEM)));
+ // Check if selection includes at least one item with correct input type
+ else if (!type_items_map.keys().contains(input_type)) {
+ enabled_itr.remove();
+ disabled_tools.insert(
+ tool_item,
+ tr("Tool Requires item type %1 selected")
+ .arg(ITEM_TYPES_STRINGS.value(input_type -
+ CloudComposerItem::CLOUD_COMPOSER_ITEM)));
}
- //Check if any of selected items have required children
- else if ( !required_children_types.empty ())
- {
- QList <QStandardItem*> matching_selected_items = type_items_map.values (input_type);
+ // Check if any of selected items have required children
+ else if (!required_children_types.empty()) {
+ QList<QStandardItem*> matching_selected_items = type_items_map.values(input_type);
bool found_valid_items = false;
- QList <CloudComposerItem::ItemType> missing_children = required_children_types;
- foreach (QStandardItem* item, matching_selected_items)
- {
- QList <CloudComposerItem::ItemType> found_children_types;
- if (!item->hasChildren ())
+ QList<CloudComposerItem::ItemType> missing_children = required_children_types;
+ foreach (QStandardItem* item, matching_selected_items) {
+ QList<CloudComposerItem::ItemType> found_children_types;
+ if (!item->hasChildren())
continue;
-
- //Find types of all children
+
+ // Find types of all children
for (int i = 0; i < item->rowCount(); ++i)
- found_children_types.append ( static_cast<CloudComposerItem::ItemType>(item->child (i)->type ()));
- //Make temporary copy, remove type from it if is present as child
- QList <CloudComposerItem::ItemType> req_children_temp = required_children_types;
+ found_children_types.append(
+ static_cast<CloudComposerItem::ItemType>(item->child(i)->type()));
+ // Make temporary copy, remove type from it if is present as child
+ QList<CloudComposerItem::ItemType> req_children_temp = required_children_types;
foreach (CloudComposerItem::ItemType type, found_children_types)
- req_children_temp.removeAll (type);
- //If temporary is empty, we found all required children
- if (req_children_temp.isEmpty ())
- {
+ req_children_temp.removeAll(type);
+ // If temporary is empty, we found all required children
+ if (req_children_temp.isEmpty()) {
found_valid_items = true;
break;
}
- //Otherwise, set missing children list
- if (req_children_temp.size () < missing_children.size ())
+ // Otherwise, set missing children list
+ if (req_children_temp.size() < missing_children.size())
missing_children = req_children_temp;
-
-
}
- //If we didn't find all required children
- if (!found_valid_items)
- {
- enabled_itr.remove ();
+ // If we didn't find all required children
+ if (!found_valid_items) {
+ enabled_itr.remove();
QString missing_children_string;
foreach (CloudComposerItem::ItemType type, missing_children)
- missing_children_string.append (" "+ITEM_TYPES_STRINGS.value (type - CloudComposerItem::CLOUD_COMPOSER_ITEM));
- disabled_tools.insert (tool_item, tr ("Tool Requires child item of type(s) %1").arg (missing_children_string));
+ missing_children_string.append(
+ " " +
+ ITEM_TYPES_STRINGS.value(type - CloudComposerItem::CLOUD_COMPOSER_ITEM));
+ disabled_tools.insert(
+ tool_item,
+ tr("Tool Requires child item of type(s) %1").arg(missing_children_string));
}
}
}
- foreach (QStandardItem* tool, tool_items)
- {
- if (enabled_tools.contains (tool))
- {
- //qDebug () << tool->text() << " is enabled!";
- tool->setToolTip (tool->text() + " is enabled");
+ foreach (QStandardItem* tool, tool_items) {
+ if (enabled_tools.contains(tool)) {
+ // qDebug () << tool->text() << " is enabled!";
+ tool->setToolTip(tool->text() + " is enabled");
}
- else
- {
- // qDebug () << tool->text() << " disabled: "<<disabled_tools.value (tool);
- tool->setToolTip (disabled_tools.value (tool));
- tool->setEnabled (false);
+ else {
+ // qDebug () << tool->text() << " disabled: "<<disabled_tools.value (tool);
+ tool->setToolTip(disabled_tools.value(tool));
+ tool->setEnabled(false);
}
}
-
-
-
}
-#include <pcl/apps/cloud_composer/transform_clouds.h>
+#include <pcl/apps/cloud_composer/impl/transform_clouds.hpp>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
+#include <pcl/apps/cloud_composer/transform_clouds.h>
#include <pcl/point_types.h>
-#include <pcl/apps/cloud_composer/impl/transform_clouds.hpp>
-
-pcl::cloud_composer::TransformClouds::TransformClouds (QMap <QString, vtkSmartPointer<vtkMatrix4x4> > transform_map, QObject* parent)
- : ModifyItemTool (nullptr, parent)
- , transform_map_ (std::move(transform_map))
-{
-
-}
+pcl::cloud_composer::TransformClouds::TransformClouds(
+ QMap<QString, vtkSmartPointer<vtkMatrix4x4>> transform_map, QObject* parent)
+: ModifyItemTool(nullptr, parent), transform_map_(std::move(transform_map))
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::TransformClouds::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::TransformClouds::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType type)
{
- if (type != PointTypeFlags::NONE)
- {
- switch ((std::uint8_t) type)
- {
- case (PointTypeFlags::XYZ):
- return this->performTemplatedAction<pcl::PointXYZ> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
- return this->performTemplatedAction<pcl::PointXYZRGB> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
- return this->performTemplatedAction<pcl::PointXYZRGBA> (input_data);
+ if (type != PointTypeFlags::NONE) {
+ switch ((std::uint8_t)type) {
+ case (PointTypeFlags::XYZ):
+ return this->performTemplatedAction<pcl::PointXYZ>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
+ return this->performTemplatedAction<pcl::PointXYZRGB>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
+ return this->performTemplatedAction<pcl::PointXYZRGBA>(input_data);
}
}
-
- QList <CloudComposerItem*> output;
- qCritical () << "Transform requires templated types!";
-
+ QList<CloudComposerItem*> output;
+
+ qCritical() << "Transform requires templated types!";
+
return output;
}
-#include <pcl/apps/cloud_composer/work_queue.h>
#include <pcl/apps/cloud_composer/tool_interface/abstract_tool.h>
+#include <pcl/apps/cloud_composer/work_queue.h>
-pcl::cloud_composer::WorkQueue::WorkQueue (QObject* parent)
- : QObject (parent)
-{
-
-
-
-}
+pcl::cloud_composer::WorkQueue::WorkQueue(QObject* parent) : QObject(parent) {}
void
-pcl::cloud_composer::WorkQueue::enqueueNewAction (AbstractTool* new_tool, ConstItemList input_data)
+pcl::cloud_composer::WorkQueue::enqueueNewAction(AbstractTool* new_tool,
+ ConstItemList input_data)
{
ActionPair new_action;
- //Create a command which will manage data for the tool
- new_action.command = new_tool->createCommand (std::move(input_data));
+ // Create a command which will manage data for the tool
+ new_action.command = new_tool->createCommand(std::move(input_data));
new_action.tool = new_tool;
-
- work_queue_.enqueue (new_action);
- checkQueue ();
+
+ work_queue_.enqueue(new_action);
+ checkQueue();
}
void
-pcl::cloud_composer::WorkQueue::actionFinished (ActionPair finished_action)
+pcl::cloud_composer::WorkQueue::actionFinished(ActionPair finished_action)
{
- //Signal the project model that the command is done
- emit commandComplete (finished_action.command);
-
- //Queue the tool for deletion
- finished_action.tool->deleteLater ();
- //Check if there are any remaining commands in queue
- checkQueue ();
-
+ // Signal the project model that the command is done
+ emit commandComplete(finished_action.command);
+
+ // Queue the tool for deletion
+ finished_action.tool->deleteLater();
+ // Check if there are any remaining commands in queue
+ checkQueue();
}
void
-pcl::cloud_composer::WorkQueue::checkQueue ( )
+pcl::cloud_composer::WorkQueue::checkQueue()
{
- if (work_queue_.length () > 0)
- {
- ActionPair action_to_execute = work_queue_.dequeue ();
- if (action_to_execute.command->runCommand (action_to_execute.tool))
- {
- //Success, send the command back to the main thread
- actionFinished (action_to_execute);
+ if (work_queue_.length() > 0) {
+ ActionPair action_to_execute = work_queue_.dequeue();
+ if (action_to_execute.command->runCommand(action_to_execute.tool)) {
+ // Success, send the command back to the main thread
+ actionFinished(action_to_execute);
}
- else
- {
- qDebug () << "FAILED TO EXECUTE COMMAND";
- //Failure, what to do with data??
+ else {
+ qDebug() << "FAILED TO EXECUTE COMMAND";
+ // Failure, what to do with data??
}
-
-
}
-
-
}
-#include <pcl/apps/cloud_composer/tools/euclidean_clustering.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
-#include <pcl/memory.h> // for pcl::make_shared
-#include <pcl/point_types.h>
+#include <pcl/apps/cloud_composer/tools/euclidean_clustering.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>
+#include <pcl/memory.h> // for pcl::make_shared
+#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::EuclideanClusteringTool::EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent)
- : SplitItemTool (parameter_model, parent)
-{
-
-}
+pcl::cloud_composer::EuclideanClusteringTool::EuclideanClusteringTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: SplitItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::EuclideanClusteringTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::EuclideanClusteringTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in Euclidean Clustering Tool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in Euclidean Clustering Tool!";
return output;
}
- if ( input_data.size () > 1)
- {
- qWarning () << "Input vector has more than one item in Euclidean Clustering!";
+ if (input_data.size() > 1) {
+ qWarning() << "Input vector has more than one item in Euclidean Clustering!";
}
- input_item = input_data.value (0);
+ input_item = input_data.value(0);
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
- {
- const CloudItem* cloud_item = dynamic_cast <const CloudItem*> (input_item);
- if ( cloud_item->isSanitized())
- {
- double cluster_tolerance = parameter_model_->getProperty ("Cluster Tolerance").toDouble();
- int min_cluster_size = parameter_model_->getProperty ("Min Cluster Size").toInt();
- int max_cluster_size = parameter_model_->getProperty ("Max Cluster Size").toInt();
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
+ const CloudItem* cloud_item = dynamic_cast<const CloudItem*>(input_item);
+ if (cloud_item->isSanitized()) {
+ double cluster_tolerance =
+ parameter_model_->getProperty("Cluster Tolerance").toDouble();
+ int min_cluster_size = parameter_model_->getProperty("Min Cluster Size").toInt();
+ int max_cluster_size = parameter_model_->getProperty("Max Cluster Size").toInt();
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
- //Get the cloud in template form
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
- pcl::fromPCLPointCloud2 (*input_cloud, *cloud);
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+ // Get the cloud in template form
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::fromPCLPointCloud2(*input_cloud, *cloud);
//////////////// THE WORK - COMPUTING CLUSTERS ///////////////////
// Creating the KdTree object for the search method of the extraction
- pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
- tree->setInputCloud (cloud);
+ pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(
+ new pcl::search::KdTree<pcl::PointXYZ>);
+ tree->setInputCloud(cloud);
std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
- ec.setClusterTolerance (cluster_tolerance);
- ec.setMinClusterSize (min_cluster_size);
- ec.setMaxClusterSize (max_cluster_size);
- ec.setSearchMethod (tree);
- ec.setInputCloud (cloud);
- ec.extract (cluster_indices);
+ ec.setClusterTolerance(cluster_tolerance);
+ ec.setMinClusterSize(min_cluster_size);
+ ec.setMaxClusterSize(max_cluster_size);
+ ec.setSearchMethod(tree);
+ ec.setInputCloud(cloud);
+ ec.extract(cluster_indices);
//////////////////////////////////////////////////////////////////
- //Get copies of the original origin and orientation
- Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
- Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
- //Vector to accumulate the extracted indices
- pcl::IndicesPtr extracted_indices (new pcl::Indices ());
- //Put found clusters into new cloud_items!
- qDebug () << "Found "<<cluster_indices.size ()<<" clusters!";
+ // Get copies of the original origin and orientation
+ Eigen::Vector4f source_origin =
+ input_item->data(ItemDataRole::ORIGIN).value<Eigen::Vector4f>();
+ Eigen::Quaternionf source_orientation =
+ input_item->data(ItemDataRole::ORIENTATION).value<Eigen::Quaternionf>();
+ // Vector to accumulate the extracted indices
+ pcl::IndicesPtr extracted_indices(new pcl::Indices());
+ // Put found clusters into new cloud_items!
+ qDebug() << "Found " << cluster_indices.size() << " clusters!";
int cluster_count = 0;
pcl::ExtractIndices<pcl::PCLPointCloud2> filter;
- for (const auto& cluster : cluster_indices)
- {
- filter.setInputCloud (input_cloud);
- // It's annoying that I have to do this, but Euclidean returns a PointIndices struct
- pcl::PointIndices::ConstPtr indices_ptr = pcl::make_shared<pcl::PointIndices>(cluster);
- filter.setIndices (indices_ptr);
- extracted_indices->insert (extracted_indices->end (), cluster.indices.begin (), cluster.indices.end ());
- //This means remove the other points
- filter.setKeepOrganized (false);
- pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2);
- filter.filter (*cloud_filtered);
+ for (const auto& cluster : cluster_indices) {
+ filter.setInputCloud(input_cloud);
+ // It's annoying that I have to do this, but Euclidean returns a PointIndices
+ // struct
+ pcl::PointIndices::ConstPtr indices_ptr =
+ pcl::make_shared<pcl::PointIndices>(cluster);
+ filter.setIndices(indices_ptr);
+ extracted_indices->insert(
+ extracted_indices->end(), cluster.indices.begin(), cluster.indices.end());
+ // This means remove the other points
+ filter.setKeepOrganized(false);
+ pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2);
+ filter.filter(*cloud_filtered);
qDebug() << "Cluster has " << cloud_filtered->width << " data points.";
- CloudItem* cloud_item = new CloudItem (input_item->text ()+tr("-Clstr %1").arg(cluster_count)
- , cloud_filtered
- , source_origin
- , source_orientation);
- output.append (cloud_item);
+ CloudItem* cloud_item =
+ new CloudItem(input_item->text() + tr("-Clstr %1").arg(cluster_count),
+ cloud_filtered,
+ source_origin,
+ source_orientation);
+ output.append(cloud_item);
++cluster_count;
}
- //We copy input cloud over for special case that no clusters found, since ExtractIndices doesn't work for 0 length vectors
- pcl::PCLPointCloud2::Ptr remainder_cloud (new pcl::PCLPointCloud2(*input_cloud));
- if (!cluster_indices.empty ())
- {
- //make a cloud containing all the remaining points
- filter.setIndices (extracted_indices);
- filter.setNegative (true);
- filter.filter (*remainder_cloud);
+ // We copy input cloud over for special case that no clusters found, since
+ // ExtractIndices doesn't work for 0 length vectors
+ pcl::PCLPointCloud2::Ptr remainder_cloud(new pcl::PCLPointCloud2(*input_cloud));
+ if (!cluster_indices.empty()) {
+ // make a cloud containing all the remaining points
+ filter.setIndices(extracted_indices);
+ filter.setNegative(true);
+ filter.filter(*remainder_cloud);
}
- qDebug() << "Cloud has " << remainder_cloud->width << " data points after clusters removed.";
- CloudItem* cloud_item = new CloudItem (input_item->text ()+ " unclustered"
- , remainder_cloud
- , source_origin
- , source_orientation);
- output.push_front (cloud_item);
+ qDebug() << "Cloud has " << remainder_cloud->width
+ << " data points after clusters removed.";
+ CloudItem* cloud_item = new CloudItem(input_item->text() + " unclustered",
+ remainder_cloud,
+ source_origin,
+ source_orientation);
+ output.push_front(cloud_item);
}
else
- qCritical () << "Input item in Clustering is not SANITIZED!!!";
+ qCritical() << "Input item in Clustering is not SANITIZED!!!";
}
- else
- {
- qCritical () << "Input item in Clustering is not a cloud!!!";
+ else {
+ qCritical() << "Input item in Clustering is not a cloud!!!";
}
-
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::EuclideanClusteringToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::EuclideanClusteringToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
- parameter_model->addProperty ("Cluster Tolerance", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Min Cluster Size", 100, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Max Cluster Size", 25000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Cluster Tolerance", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Min Cluster Size", 100, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Max Cluster Size", 25000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/fpfh_estimation.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-#include <pcl/apps/cloud_composer/items/normals_item.h>
#include <pcl/apps/cloud_composer/items/fpfh_item.h>
-
+#include <pcl/apps/cloud_composer/items/normals_item.h>
+#include <pcl/apps/cloud_composer/tools/fpfh_estimation.h>
#include <pcl/features/fpfh.h>
-#include <pcl/point_types.h>
#include <pcl/filters/filter.h>
+#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::FPFHEstimationTool::FPFHEstimationTool (PropertiesModel* parameter_model, QObject* parent)
- : NewItemTool (parameter_model, parent)
-{
+pcl::cloud_composer::FPFHEstimationTool::FPFHEstimationTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: NewItemTool(parameter_model, parent)
+{}
-
-}
-
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::FPFHEstimationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::FPFHEstimationTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in FPFH Estimation Tool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in FPFH Estimation Tool!";
return output;
}
- if ( input_data.size () > 1)
- {
- qWarning () << "Input vector has more than one item in FPFH Estimation!";
+ if (input_data.size() > 1) {
+ qWarning() << "Input vector has more than one item in FPFH Estimation!";
}
- input_item = input_data.value (0);
-
-
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
- {
- //Check if this cloud has normals computed!
- QList <CloudComposerItem*> normals_list = input_item->getChildren (CloudComposerItem::NORMALS_ITEM);
- if ( normals_list.empty () )
- {
- qCritical () << "No normals item child found in this cloud item";
+ input_item = input_data.value(0);
+
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
+ // Check if this cloud has normals computed!
+ QList<CloudComposerItem*> normals_list =
+ input_item->getChildren(CloudComposerItem::NORMALS_ITEM);
+ if (normals_list.empty()) {
+ qCritical() << "No normals item child found in this cloud item";
return output;
}
- qDebug () << "Found item text="<<normals_list.at(0)->text();
+ qDebug() << "Found item text=" << normals_list.at(0)->text();
double radius = parameter_model_->getProperty("Radius").toDouble();
-
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
- //Get the cloud in template form
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
- pcl::fromPCLPointCloud2 (*input_cloud, *cloud);
-
- //Get the normals cloud, we just use the first normals that were found if there are more than one
- pcl::PointCloud<pcl::Normal>::ConstPtr input_normals = normals_list.value(0)->data(ItemDataRole::CLOUD_TEMPLATED).value <pcl::PointCloud<pcl::Normal>::ConstPtr> ();
-
+
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+ // Get the cloud in template form
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::fromPCLPointCloud2(*input_cloud, *cloud);
+
+ // Get the normals cloud, we just use the first normals that were found if there are
+ // more than one
+ pcl::PointCloud<pcl::Normal>::ConstPtr input_normals =
+ normals_list.value(0)
+ ->data(ItemDataRole::CLOUD_TEMPLATED)
+ .value<pcl::PointCloud<pcl::Normal>::ConstPtr>();
+
pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh;
- // qDebug () << "Input cloud size = "<<cloud->size ();
+ // qDebug () << "Input cloud size = "<<cloud->size ();
//////////////// THE WORK - COMPUTING FPFH ///////////////////
// Create the FPFH estimation class, and pass the input dataset+normals to it
- fpfh.setInputCloud (cloud);
- fpfh.setInputNormals (input_normals);
+ fpfh.setInputCloud(cloud);
+ fpfh.setInputNormals(input_normals);
// Create an empty kdtree representation, and pass it to the FPFH estimation object.
- // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
- qDebug () << "Building KD Tree";
- pcl::search::KdTree<PointXYZ>::Ptr tree (new pcl::search::KdTree<PointXYZ>);
- fpfh.setSearchMethod (tree);
+ // Its content will be filled inside the object, based on the given input dataset
+ // (as no other search surface is given).
+ qDebug() << "Building KD Tree";
+ pcl::search::KdTree<PointXYZ>::Ptr tree(new pcl::search::KdTree<PointXYZ>);
+ fpfh.setSearchMethod(tree);
// Output datasets
- pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs (new pcl::PointCloud<pcl::FPFHSignature33> ());
+ pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs(
+ new pcl::PointCloud<pcl::FPFHSignature33>());
// Use all neighbors in a sphere of radius 5cm
- // IMPORTANT: the radius used here has to be larger than the radius used to estimate the surface normals!!!
- fpfh.setRadiusSearch (radius);
+ // IMPORTANT: the radius used here has to be larger than the radius used to estimate
+ // the surface normals!!!
+ fpfh.setRadiusSearch(radius);
// Compute the features
- qDebug () << "Computing FPFH features";
- fpfh.compute (*fpfhs);
- qDebug () << "Size of computed features ="<<fpfhs->width;
+ qDebug() << "Computing FPFH features";
+ fpfh.compute(*fpfhs);
+ qDebug() << "Size of computed features =" << fpfhs->width;
//////////////////////////////////////////////////////////////////
- FPFHItem* fpfh_item = new FPFHItem (tr("FPFH r=%1").arg(radius),fpfhs,radius);
- output.append (fpfh_item);
+ FPFHItem* fpfh_item = new FPFHItem(tr("FPFH r=%1").arg(radius), fpfhs, radius);
+ output.append(fpfh_item);
}
- else
- {
- qCritical () << "Input item in FPFH Estimation is not a cloud!!!";
+ else {
+ qCritical() << "Input item in FPFH Estimation is not a cloud!!!";
}
-
-
+
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::FPFHEstimationToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::FPFHEstimationToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Radius", 0.03, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+
+ parameter_model->addProperty("Radius", 0.03, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/normal_estimation.h>
#include <pcl/apps/cloud_composer/items/normals_item.h>
-
+#include <pcl/apps/cloud_composer/tools/normal_estimation.h>
#include <pcl/features/normal_3d.h>
#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::NormalEstimationTool::NormalEstimationTool (PropertiesModel* parameter_model, QObject* parent)
- : NewItemTool (parameter_model, parent)
-{
-
-
-}
+pcl::cloud_composer::NormalEstimationTool::NormalEstimationTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: NewItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::NormalEstimationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::NormalEstimationTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in Normal Estimation Tool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in Normal Estimation Tool!";
return output;
}
- if ( input_data.size () > 1)
- {
- qWarning () << "Input vector has more than one item in Normal Estimation!";
+ if (input_data.size() > 1) {
+ qWarning() << "Input vector has more than one item in Normal Estimation!";
}
- input_item = input_data.value (0);
-
+ input_item = input_data.value(0);
+
pcl::PCLPointCloud2::ConstPtr input_cloud;
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
- {
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
double radius = parameter_model_->getProperty("Radius").toDouble();
- qDebug () << "Received Radius = " <<radius;
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
- qDebug () << "Got cloud size = "<<input_cloud->width;
+ qDebug() << "Received Radius = " << radius;
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+ qDebug() << "Got cloud size = " << input_cloud->width;
//////////////// THE WORK - COMPUTING NORMALS ///////////////////
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
- pcl::fromPCLPointCloud2 (*input_cloud, *cloud);
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::fromPCLPointCloud2(*input_cloud, *cloud);
// Create the normal estimation class, and pass the input dataset to it
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
- ne.setInputCloud (cloud);
+ ne.setInputCloud(cloud);
- // Create an empty kdtree representation, and pass it to the normal estimation object.
- // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
- pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
- ne.setSearchMethod (tree);
+ // Create an empty kdtree representation, and pass it to the normal estimation
+ // object. Its content will be filled inside the object, based on the given input
+ // dataset (as no other search surface is given).
+ pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(
+ new pcl::search::KdTree<pcl::PointXYZ>());
+ ne.setSearchMethod(tree);
// Output datasets
- pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
+ pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
// Use all neighbors in a sphere of radius 3cm
- ne.setRadiusSearch (radius);
+ ne.setRadiusSearch(radius);
// Compute the features
- ne.compute (*cloud_normals);
+ ne.compute(*cloud_normals);
//////////////////////////////////////////////////////////////////
- NormalsItem* normals_item = new NormalsItem (tr("Normals r=%1").arg(radius),cloud_normals,radius);
- output.append (normals_item);
- qDebug () << "Calced normals";
+ NormalsItem* normals_item =
+ new NormalsItem(tr("Normals r=%1").arg(radius), cloud_normals, radius);
+ output.append(normals_item);
+ qDebug() << "Calced normals";
}
- else
- {
- qDebug () << "Input item in Normal Estimation is not a cloud!!!";
+ else {
+ qDebug() << "Input item in Normal Estimation is not a cloud!!!";
}
-
-
+
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::NormalEstimationToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::NormalEstimationToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Radius", 0.04, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+
+ parameter_model->addProperty("Radius", 0.04, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/organized_segmentation.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
-#include <pcl/point_types.h>
+#include <pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp>
+#include <pcl/apps/cloud_composer/tools/organized_segmentation.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>
-
-
-#include <pcl/apps/cloud_composer/tools/impl/organized_segmentation.hpp>
+#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::OrganizedSegmentationTool::OrganizedSegmentationTool (PropertiesModel* parameter_model, QObject* parent)
-: SplitItemTool (parameter_model, parent)
-{
-
-}
+pcl::cloud_composer::OrganizedSegmentationTool::OrganizedSegmentationTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: SplitItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::OrganizedSegmentationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::OrganizedSegmentationTool::performAction(
+ ConstItemList input_data, PointTypeFlags::PointType type)
{
- if (type != PointTypeFlags::NONE)
- {
- switch ((std::uint8_t) type)
- {
- case (PointTypeFlags::XYZ):
- return this->performTemplatedAction<pcl::PointXYZ> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
- return this->performTemplatedAction<pcl::PointXYZRGB> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
- return this->performTemplatedAction<pcl::PointXYZRGBA> (input_data);
+ if (type != PointTypeFlags::NONE) {
+ switch ((std::uint8_t)type) {
+ case (PointTypeFlags::XYZ):
+ return this->performTemplatedAction<pcl::PointXYZ>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
+ return this->performTemplatedAction<pcl::PointXYZRGB>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
+ return this->performTemplatedAction<pcl::PointXYZRGBA>(input_data);
}
}
-
- QList <CloudComposerItem*> output;
-
- qCritical () << "organized_segmentation requires templated types!";
-
+
+ QList<CloudComposerItem*> output;
+
+ qCritical() << "organized_segmentation requires templated types!";
+
return output;
-}
+}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::OrganizedSegmentationToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::OrganizedSegmentationToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Min Inliers", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Min Plane Size", 10000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Angular Threshold", 2.0, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Distance Threshold", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Cluster Dist. Thresh.", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Min Cluster Size", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
-
+
+ parameter_model->addProperty(
+ "Min Inliers", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Min Plane Size", 10000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Angular Threshold", 2.0, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Distance Threshold", 0.02, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Cluster Dist. Thresh.", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Min Cluster Size", 1000, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/sanitize_cloud.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
+#include <pcl/apps/cloud_composer/tools/sanitize_cloud.h>
#include <pcl/filters/passthrough.h>
-#include <pcl/memory.h> // for pcl::make_shared
+#include <pcl/memory.h> // for pcl::make_shared
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::SanitizeCloudTool::SanitizeCloudTool (PropertiesModel* parameter_model, QObject* parent)
-: ModifyItemTool (parameter_model, parent)
-{
-}
+pcl::cloud_composer::SanitizeCloudTool::SanitizeCloudTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: ModifyItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::SanitizeCloudTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::SanitizeCloudTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in SanitizeCloudTool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in SanitizeCloudTool!";
return output;
}
- input_item = input_data.value (0);
-
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM )
- {
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
-
- bool keep_organized = parameter_model_->getProperty("Keep Organized").toBool ();
-
+ input_item = input_data.value(0);
+
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+
+ bool keep_organized = parameter_model_->getProperty("Keep Organized").toBool();
+
//////////////// THE WORK - FILTERING NANS ///////////////////
// Create the filtering object
pcl::PassThrough<pcl::PCLPointCloud2> pass_filter;
- pass_filter.setInputCloud (input_cloud);
- pass_filter.setKeepOrganized (keep_organized);
-
- //Create output cloud
- pcl::PCLPointCloud2::Ptr cloud_filtered = pcl::make_shared<pcl::PCLPointCloud2> ();
- //Filter!
- pass_filter.filter (*cloud_filtered);
-
+ pass_filter.setInputCloud(input_cloud);
+ pass_filter.setKeepOrganized(keep_organized);
+
+ // Create output cloud
+ pcl::PCLPointCloud2::Ptr cloud_filtered = pcl::make_shared<pcl::PCLPointCloud2>();
+ // Filter!
+ pass_filter.filter(*cloud_filtered);
+
//////////////////////////////////////////////////////////////////
- //Get copies of the original origin and orientation
- Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
- Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
- //Put the modified cloud into an item, stick in output
- CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" sanitized")
- , cloud_filtered
- , source_origin
- , source_orientation);
-
-
- output.append (cloud_item);
+ // Get copies of the original origin and orientation
+ Eigen::Vector4f source_origin =
+ input_item->data(ItemDataRole::ORIGIN).value<Eigen::Vector4f>();
+ Eigen::Quaternionf source_orientation =
+ input_item->data(ItemDataRole::ORIENTATION).value<Eigen::Quaternionf>();
+ // Put the modified cloud into an item, stick in output
+ CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" sanitized"),
+ cloud_filtered,
+ source_origin,
+ source_orientation);
+
+ output.append(cloud_item);
}
- else
- {
- qDebug () << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!";
+ else {
+ qDebug() << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!";
}
-
-
+
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::SanitizeCloudToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::SanitizeCloudToolFactory::createToolParameterModel(QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Keep Organized", false, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+
+ parameter_model->addProperty(
+ "Keep Organized", false, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-
-#include <pcl/apps/cloud_composer/tools/statistical_outlier_removal.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
+#include <pcl/apps/cloud_composer/tools/statistical_outlier_removal.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::StatisticalOutlierRemovalTool::StatisticalOutlierRemovalTool (PropertiesModel* parameter_model, QObject* parent)
- : ModifyItemTool (parameter_model, parent)
-{
+pcl::cloud_composer::StatisticalOutlierRemovalTool::StatisticalOutlierRemovalTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: ModifyItemTool(parameter_model, parent)
+{}
-
-}
-
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::StatisticalOutlierRemovalTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::StatisticalOutlierRemovalTool::performAction(
+ ConstItemList input_data, PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in StatisticalOutlierRemovalTool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in StatisticalOutlierRemovalTool!";
return output;
}
- if ( input_data.size () > 1)
- {
- qWarning () << "Input vector has more than one item in StatisticalOutlierRemovalTool";
+ if (input_data.size() > 1) {
+ qWarning()
+ << "Input vector has more than one item in StatisticalOutlierRemovalTool";
}
- input_item = input_data.value (0);
- if ( !input_item->isSanitized () )
- {
- qCritical () << "StatisticalOutlierRemovalTool requires sanitized input!";
+ input_item = input_data.value(0);
+ if (!input_item->isSanitized()) {
+ qCritical() << "StatisticalOutlierRemovalTool requires sanitized input!";
return output;
}
-
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM )
- {
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
-
- int mean_k = parameter_model_->getProperty("Mean K").toInt ();
- double std_dev_thresh = parameter_model_->getProperty ("Std Dev Thresh").toDouble ();
-
+
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+
+ int mean_k = parameter_model_->getProperty("Mean K").toInt();
+ double std_dev_thresh = parameter_model_->getProperty("Std Dev Thresh").toDouble();
+
//////////////// THE WORK - FILTERING OUTLIERS ///////////////////
// Create the filtering object
pcl::StatisticalOutlierRemoval<pcl::PCLPointCloud2> sor;
- sor.setInputCloud (input_cloud);
- sor.setMeanK (mean_k);
- sor.setStddevMulThresh (std_dev_thresh);
-
- //Create output cloud
- pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2);
- //Filter!
- sor.filter (*cloud_filtered);
+ sor.setInputCloud(input_cloud);
+ sor.setMeanK(mean_k);
+ sor.setStddevMulThresh(std_dev_thresh);
+
+ // Create output cloud
+ pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2);
+ // Filter!
+ sor.filter(*cloud_filtered);
//////////////////////////////////////////////////////////////////
- //Get copies of the original origin and orientation
- Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
- Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
- //Put the modified cloud into an item, stick in output
- CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" sor filtered")
- , cloud_filtered
- , source_origin
- , source_orientation);
+ // Get copies of the original origin and orientation
+ Eigen::Vector4f source_origin =
+ input_item->data(ItemDataRole::ORIGIN).value<Eigen::Vector4f>();
+ Eigen::Quaternionf source_orientation =
+ input_item->data(ItemDataRole::ORIENTATION).value<Eigen::Quaternionf>();
+ // Put the modified cloud into an item, stick in output
+ CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" sor filtered"),
+ cloud_filtered,
+ source_origin,
+ source_orientation);
-
- output.append (cloud_item);
+ output.append(cloud_item);
}
- else
- {
- qDebug () << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!";
+ else {
+ qDebug() << "Input item in StatisticalOutlierRemovalTool is not a cloud!!!";
}
-
-
+
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::StatisticalOutlierRemovalToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::StatisticalOutlierRemovalToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Mean K", 50, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Std Dev Thresh", 1.0, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+
+ parameter_model->addProperty("Mean K", 50, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Std Dev Thresh", 1.0, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/supervoxels.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
+#include <pcl/apps/cloud_composer/tools/impl/supervoxels.hpp>
+#include <pcl/apps/cloud_composer/tools/supervoxels.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/kdtree/kdtree.h>
-#include <pcl/point_types.h>
#include <pcl/segmentation/extract_clusters.h>
-
-#include <pcl/apps/cloud_composer/tools/impl/supervoxels.hpp>
+#include <pcl/point_types.h>
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::SupervoxelsTool::SupervoxelsTool (PropertiesModel* parameter_model, QObject* parent)
-: SplitItemTool (parameter_model, parent)
-{
-
-}
+pcl::cloud_composer::SupervoxelsTool::SupervoxelsTool(PropertiesModel* parameter_model,
+ QObject* parent)
+: SplitItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::SupervoxelsTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::SupervoxelsTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType type)
{
- if (type != PointTypeFlags::NONE)
- {
- switch ((std::uint8_t) type)
- {
- case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
- return this->performTemplatedAction<pcl::PointXYZRGB> (input_data);
- case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
- return this->performTemplatedAction<pcl::PointXYZRGBA> (input_data);
+ if (type != PointTypeFlags::NONE) {
+ switch ((std::uint8_t)type) {
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGB):
+ return this->performTemplatedAction<pcl::PointXYZRGB>(input_data);
+ case (PointTypeFlags::XYZ | PointTypeFlags::RGBA):
+ return this->performTemplatedAction<pcl::PointXYZRGBA>(input_data);
}
}
-
- QList <CloudComposerItem*> output;
-
- qCritical () << "supervoxels requires templated types!";
-
- return output;
-}
-template QList <pcl::cloud_composer::CloudComposerItem*> pcl::cloud_composer::SupervoxelsTool::performTemplatedAction <pcl::PointXYZRGB> (const QList <const CloudComposerItem*>&);
-//template QList <pcl::cloud_composer::CloudComposerItem*> pcl::cloud_composer::SupervoxelsTool::performTemplatedAction <pcl::PointXYZRGBA> (const QList <const CloudComposerItem*>&);
+ QList<CloudComposerItem*> output;
+
+ qCritical() << "supervoxels requires templated types!";
+
+ return output;
+}
+template QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::SupervoxelsTool::performTemplatedAction<pcl::PointXYZRGB>(
+ const QList<const CloudComposerItem*>&);
+// template QList <pcl::cloud_composer::CloudComposerItem*>
+// pcl::cloud_composer::SupervoxelsTool::performTemplatedAction <pcl::PointXYZRGBA>
+// (const QList <const CloudComposerItem*>&);
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::SupervoxelsToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::SupervoxelsToolFactory::createToolParameterModel(QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Resolution", 0.008, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Seed Resolution", 0.08, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("RGB Weight", 0.2, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Normals Weight", 0.8, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Spatial Weight", 0.4, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+
+ parameter_model->addProperty(
+ "Resolution", 0.008, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Seed Resolution", 0.08, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "RGB Weight", 0.2, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Normals Weight", 0.8, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Spatial Weight", 0.4, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
-#include <pcl/apps/cloud_composer/tools/voxel_grid_downsample.h>
#include <pcl/apps/cloud_composer/items/cloud_item.h>
-
+#include <pcl/apps/cloud_composer/tools/voxel_grid_downsample.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/point_types.h>
-
Q_PLUGIN_METADATA(IID "cloud_composer.ToolFactory/1.0")
-pcl::cloud_composer::VoxelGridDownsampleTool::VoxelGridDownsampleTool (PropertiesModel* parameter_model, QObject* parent)
- : ModifyItemTool (parameter_model, parent)
-{
-
-
-}
+pcl::cloud_composer::VoxelGridDownsampleTool::VoxelGridDownsampleTool(
+ PropertiesModel* parameter_model, QObject* parent)
+: ModifyItemTool(parameter_model, parent)
+{}
-QList <pcl::cloud_composer::CloudComposerItem*>
-pcl::cloud_composer::VoxelGridDownsampleTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
+QList<pcl::cloud_composer::CloudComposerItem*>
+pcl::cloud_composer::VoxelGridDownsampleTool::performAction(ConstItemList input_data,
+ PointTypeFlags::PointType)
{
- QList <CloudComposerItem*> output;
+ QList<CloudComposerItem*> output;
const CloudComposerItem* input_item;
// Check input data length
- if ( input_data.empty ())
- {
- qCritical () << "Empty input in VoxelGridDownsampleTool!";
+ if (input_data.empty()) {
+ qCritical() << "Empty input in VoxelGridDownsampleTool!";
return output;
}
- if ( input_data.size () > 1)
- {
- qWarning () << "Input vector has more than one item in VoxelGridDownsampleTool";
+ if (input_data.size() > 1) {
+ qWarning() << "Input vector has more than one item in VoxelGridDownsampleTool";
}
- input_item = input_data.value (0);
-
- if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
- {
- double leaf_x = parameter_model_->getProperty("Leaf Size x").toDouble ();
- double leaf_y = parameter_model_->getProperty("Leaf Size y").toDouble ();
- double leaf_z = parameter_model_->getProperty("Leaf Size z").toDouble ();
-
- pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
-
+ input_item = input_data.value(0);
+
+ if (input_item->type() == CloudComposerItem::CLOUD_ITEM) {
+ double leaf_x = parameter_model_->getProperty("Leaf Size x").toDouble();
+ double leaf_y = parameter_model_->getProperty("Leaf Size y").toDouble();
+ double leaf_z = parameter_model_->getProperty("Leaf Size z").toDouble();
+
+ pcl::PCLPointCloud2::ConstPtr input_cloud =
+ input_item->data(ItemDataRole::CLOUD_BLOB)
+ .value<pcl::PCLPointCloud2::ConstPtr>();
+
//////////////// THE WORK - FILTERING OUTLIERS ///////////////////
// Create the filtering object
pcl::VoxelGrid<pcl::PCLPointCloud2> vox_grid;
- vox_grid.setInputCloud (input_cloud);
- vox_grid.setLeafSize (float (leaf_x), float (leaf_y), float (leaf_z));
-
-
- //Create output cloud
- pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2);
- //Filter!
- vox_grid.filter (*cloud_filtered);
+ vox_grid.setInputCloud(input_cloud);
+ vox_grid.setLeafSize(float(leaf_x), float(leaf_y), float(leaf_z));
+
+ // Create output cloud
+ pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2);
+ // Filter!
+ vox_grid.filter(*cloud_filtered);
//////////////////////////////////////////////////////////////////
- //Get copies of the original origin and orientation
- Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
- Eigen::Quaternionf source_orientation = input_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
- //Put the modified cloud into an item, stick in output
- CloudItem* cloud_item = new CloudItem (input_item->text () + tr (" vox ds")
- , cloud_filtered
- , source_origin
- , source_orientation);
+ // Get copies of the original origin and orientation
+ Eigen::Vector4f source_origin =
+ input_item->data(ItemDataRole::ORIGIN).value<Eigen::Vector4f>();
+ Eigen::Quaternionf source_orientation =
+ input_item->data(ItemDataRole::ORIENTATION).value<Eigen::Quaternionf>();
+ // Put the modified cloud into an item, stick in output
+ CloudItem* cloud_item = new CloudItem(input_item->text() + tr(" vox ds"),
+ cloud_filtered,
+ source_origin,
+ source_orientation);
-
- output.append (cloud_item);
+ output.append(cloud_item);
}
- else
- {
- qDebug () << "Input item in VoxelGridDownsampleTool is not a cloud!!!";
+ else {
+ qDebug() << "Input item in VoxelGridDownsampleTool is not a cloud!!!";
}
-
-
+
return output;
}
/////////////////// PARAMETER MODEL /////////////////////////////////
pcl::cloud_composer::PropertiesModel*
-pcl::cloud_composer::VoxelGridDownsampleToolFactory::createToolParameterModel (QObject* parent)
+pcl::cloud_composer::VoxelGridDownsampleToolFactory::createToolParameterModel(
+ QObject* parent)
{
PropertiesModel* parameter_model = new PropertiesModel(parent);
-
- parameter_model->addProperty ("Leaf Size x", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Leaf Size y", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
- parameter_model->addProperty ("Leaf Size z", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
-
+ parameter_model->addProperty(
+ "Leaf Size x", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Leaf Size y", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ parameter_model->addProperty(
+ "Leaf Size z", 0.01, Qt::ItemIsEditable | Qt::ItemIsEnabled);
+
return parameter_model;
}
#include <QOpenGLWidget>
+#include <array> // for std::array
#include <functional>
class Selection;
auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio,
- event -> modifiers(), event -> buttons());
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ tool_ptr_ -> start(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> buttons());
+#else
+ tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons());
+#endif
update();
}
auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio,
- event -> modifiers(), event -> buttons());
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ tool_ptr_ -> update(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> buttons());
+#else
+ tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons());
+#endif
update();
}
auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio,
- event -> modifiers(), event -> button());
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ tool_ptr_ -> end(event -> position().x()*ratio, event -> position().y()*ratio, event -> modifiers(), event -> button());
+#else
+ tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> button());
+#endif
update();
}
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/pcl_visualizer.h>
+#include <chrono>
#include <thread>
using namespace pcl;
"${PCL_SOURCE_DIR}/test/milk_cartoon_all_small_clorox.pcd")
PCL_ADD_BENCHMARK(search_radius_search FILES search/radius_search.cpp
- LINK_WITH pcl_io pcl_search
- ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd"
- "${PCL_SOURCE_DIR}/test/milk_cartoon_all_small_clorox.pcd")
-
+ LINK_WITH pcl_io pcl_search pcl_filters
+ ARGUMENTS "${PCL_SOURCE_DIR}/test/table_scene_mug_stereo_textured.pcd")
+
\ No newline at end of file
+#include <pcl/filters/filter.h>
#include <pcl/io/pcd_io.h>
+#include <pcl/search/kdtree.h>
+#include <pcl/search/kdtree_nanoflann.h>
#include <pcl/search/organized.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <chrono>
-static void
-BM_OrganizedNeighborSearch(benchmark::State& state, const std::string& file)
+void
+print_help()
{
- pcl::PointCloud<pcl::PointXYZ>::Ptr cloudIn(new pcl::PointCloud<pcl::PointXYZ>);
- pcl::PCDReader reader;
- reader.read(file, *cloudIn);
-
- pcl::search::OrganizedNeighbor<pcl::PointXYZ> organizedNeighborSearch;
- organizedNeighborSearch.setInputCloud(cloudIn);
+ std::cout << "Usage: benchmark_radius_search <pcd filename>\n";
+ std::cout << "Additional argument options:\n";
+ std::cout << "Usage: benchmark_radius_search <pcd filename> <radius search> "
+ "<neighbor limit>\n";
+}
- double radiusSearchTime = 0;
- std::vector<int> indices(cloudIn->size()); // Fixed indices from 0 to cloud size
- std::iota(indices.begin(), indices.end(), 0);
+static void
+BM_RadiusSearch(benchmark::State& state,
+ const pcl::search::Search<pcl::PointXYZ>& search,
+ const pcl::PointCloud<pcl::PointXYZ>::Ptr cloudIn,
+ const double searchRadius,
+ const size_t neighborLimit)
+{
int radiusSearchIdx = 0;
+ pcl::Indices k_indices;
+ std::vector<float> k_sqr_distances;
for (auto _ : state) {
- int searchIdx = indices[radiusSearchIdx++ % indices.size()];
- double searchRadius = 0.1; // or any fixed radius like 0.05
+ state.PauseTiming();
+ int searchIdx = radiusSearchIdx++ % cloudIn->size();
+ while (!pcl::isFinite((*cloudIn)[searchIdx])) {
+ searchIdx = radiusSearchIdx++ % cloudIn->size();
+ }
+ state.ResumeTiming();
+ search.radiusSearch(
+ (*cloudIn)[searchIdx], searchRadius, k_indices, k_sqr_distances, neighborLimit);
+ }
+}
- pcl::Indices k_indices;
- std::vector<float> k_sqr_distances;
+static void
+BM_KdTreeAll(benchmark::State& state,
+ const pcl::PointCloud<pcl::PointXYZ>::Ptr cloudIn,
+ const double searchRadius,
+ const size_t neighborLimit)
+{
+ pcl::search::KdTree<pcl::PointXYZ> kdtree(false);
+ kdtree.setInputCloud(cloudIn);
+ // Leaving indices empty to have it search through all points
+ pcl::Indices indices;
+ std::vector<pcl::Indices> k_indices;
+ std::vector<std::vector<float>> k_sqr_distances;
+ for (auto _ : state) {
auto start_time = std::chrono::high_resolution_clock::now();
- organizedNeighborSearch.radiusSearch(
- (*cloudIn)[searchIdx], searchRadius, k_indices, k_sqr_distances);
+ kdtree.radiusSearch(
+ *cloudIn, indices, searchRadius, k_indices, k_sqr_distances, neighborLimit);
auto end_time = std::chrono::high_resolution_clock::now();
-
- radiusSearchTime +=
- std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time)
- .count();
+ std::chrono::duration<double> elapsed = end_time - start_time;
+ state.SetIterationTime(elapsed.count() / cloudIn->size());
}
- state.SetItemsProcessed(state.iterations());
- state.SetIterationTime(
- radiusSearchTime /
- (state.iterations() * indices.size())); // Normalize by total points processed
+ state.SetItemsProcessed(cloudIn->size());
}
int
if (argc < 2) {
std::cerr << "No test file given. Please provide a PCD file for the benchmark."
<< std::endl;
+ print_help();
return -1;
}
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloudIn(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::PCDReader reader;
+ reader.read(argv[1], *cloudIn);
+
+ // Filter out nans
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloudFiltered(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::Indices indices;
+ pcl::removeNaNFromPointCloud(*cloudIn, *cloudFiltered, indices);
+
+ double searchRadius = 0.1;
+ if (argc > 2) {
+ try {
+ searchRadius = std::abs(std::stod(argv[2]));
+ } catch (const std::invalid_argument&) {
+ std::cerr << "Error: Invalid search radius. Setting it to a default of 0.1."
+ << std::endl;
+ }
+ }
+
+ size_t neighborLimit = 0u;
+ if (argc > 3) {
+ try {
+ neighborLimit = std::stoul(argv[3]);
+ } catch (const std::invalid_argument&) {
+ std::cerr << "Error: Invalid neighbor limit. Setting it to a default of int max."
+ << std::endl;
+ }
+ }
+
+ pcl::search::OrganizedNeighbor<pcl::PointXYZ> organized_neighbor;
+ organized_neighbor.setInputCloud(cloudIn);
+ benchmark::RegisterBenchmark("OrganizedNeighborSearch",
+ &BM_RadiusSearch,
+ organized_neighbor,
+ cloudIn,
+ searchRadius,
+ neighborLimit)
+ ->Unit(benchmark::kMicrosecond);
+
+ pcl::search::KdTree<pcl::PointXYZ> kdtree(false);
+ kdtree.setInputCloud(cloudIn);
+ benchmark::RegisterBenchmark(
+ "KdTree", &BM_RadiusSearch, kdtree, cloudIn, searchRadius, neighborLimit)
+ ->Unit(benchmark::kMicrosecond);
+
benchmark::RegisterBenchmark(
- "BM_OrganizedNeighborSearch", &BM_OrganizedNeighborSearch, argv[1])
- ->Unit(benchmark::kMillisecond);
+ "KdTreeAll", &BM_KdTreeAll, cloudFiltered, searchRadius, neighborLimit)
+ ->Unit(benchmark::kMicrosecond)
+ ->UseManualTime()
+ ->Iterations(1);
+
+#if PCL_HAS_NANOFLANN
+ pcl::search::KdTreeNanoflann<pcl::PointXYZ> kdtreeNanoflann;
+ kdtreeNanoflann.setInputCloud(cloudIn);
+ benchmark::RegisterBenchmark("KdTreeNanoflann",
+ &BM_RadiusSearch,
+ kdtreeNanoflann,
+ cloudIn,
+ searchRadius,
+ neighborLimit)
+ ->Unit(benchmark::kMicrosecond);
+#endif
+
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
}
--- /dev/null
+###############################################################################
+# Check for the presence of _mm_malloc() and posix_memalign()
+function(PCL_CHECK_FOR_ALIGNMENT)
+ include(CheckCXXSourceCompiles)
+ if(NOT DEFINED HAVE_MM_MALLOC)
+ check_cxx_source_compiles("
+ // Intel compiler defines an incompatible _mm_malloc signature
+ #if defined(__INTEL_COMPILER)
+ #include <malloc.h>
+ #else
+ #include <mm_malloc.h>
+ #endif
+ int main()
+ {
+ void* mem = _mm_malloc (100, 16);
+ return 0;
+ }"
+ HAVE_MM_MALLOC)
+ endif()
+
+ if(NOT DEFINED HAVE_POSIX_MEMALIGN)
+ check_cxx_source_compiles("
+ #include <stdlib.h>
+ int main()
+ {
+ void* mem;
+ return posix_memalign (&mem, 16, 100);
+ }"
+ HAVE_POSIX_MEMALIGN)
+ endif()
+endfunction()
endif()
# get root directory of each dependency libraries to be copied to PCL/3rdParty
-get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH) # ../Boost/include/boost-x_x/ -> ../Boost/include/
-get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/include/ -> ../Boost/
-get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake
-get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/
-get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/
-get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/
-get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/
-get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/
+get_filename_component(BOOST_ROOT "${Boost_DIR}" PATH) # ../Boost/lib/cmake/Boost-X.XX.X/ -> ../Boost/lib/cmake/
+get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/lib/cmake/ -> ../Boost/lib/
+get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/lib/ -> ../Boost/
+get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake
+get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/
+get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/
+get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/
+get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/
+get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/
set(PCL_3RDPARTY_COMPONENTS)
foreach(dep Boost Qhull FLANN VTK)
function(PCL_CHECK_FOR_AVX)
set(AVX_FLAGS)
- include(CheckCXXSourceRuns)
+ include(CheckCXXSourceCompiles)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
- # Setting -march & -mtune just as required flags for check_cxx_source_runs,
- # and CMAKE_REQUIRED_FLAGS will be restored after test runs.
+ # Setting -march & -mtune just as required flags for check_cxx_source_compiles,
+ # and CMAKE_REQUIRED_FLAGS will be restored after test compiles.
set(CMAKE_REQUIRED_FLAGS "-march=native -mtune=native")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <immintrin.h>
int main()
{
HAVE_AVX2)
if(NOT HAVE_AVX2)
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <immintrin.h>
int main()
{
if(CMAKE_CXX_STANDARD MATCHES "14")
# Optional boost modules
- set(BOOST_OPTIONAL_MODULES serialization mpi)
+ set(BOOST_OPTIONAL_MODULES serialization mpi system)
# Required boost modules
- set(BOOST_REQUIRED_MODULES filesystem iostreams system)
+ set(BOOST_REQUIRED_MODULES filesystem iostreams)
else()
# Optional boost modules
- set(BOOST_OPTIONAL_MODULES filesystem serialization mpi)
+ set(BOOST_OPTIONAL_MODULES filesystem serialization mpi system)
# Required boost modules
- set(BOOST_REQUIRED_MODULES iostreams system)
+ set(BOOST_REQUIRED_MODULES iostreams)
endif()
find_package(Boost 1.71.0 QUIET COMPONENTS ${BOOST_OPTIONAL_MODULES} CONFIG)
# precision). One solution would be to use "-ffloat-store" on 32bit (see
# http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html), but that slows code down,
# so the preferred solution is to try "-mpfmath=sse" first.
- include(CheckCXXSourceRuns)
+ include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS)
set(SSE_LEVEL 0)
- check_cxx_source_runs("
- // Intel compiler defines an incompatible _mm_malloc signature
- #if defined(__INTEL_COMPILER)
- #include <malloc.h>
- #else
- #include <mm_malloc.h>
- #endif
- int main()
- {
- void* mem = _mm_malloc (100, 16);
- return 0;
- }"
- HAVE_MM_MALLOC)
-
- check_cxx_source_runs("
- #include <stdlib.h>
- int main()
- {
- void* mem;
- return posix_memalign (&mem, 16, 100);
- }"
- HAVE_POSIX_MEMALIGN)
-
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
set(CMAKE_REQUIRED_FLAGS "-msse4.2")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <emmintrin.h>
#include <nmmintrin.h>
int main ()
set(CMAKE_REQUIRED_FLAGS "-msse4.1")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <smmintrin.h>
int main ()
{
set(CMAKE_REQUIRED_FLAGS "-mssse3")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <tmmintrin.h>
int main ()
{
set(CMAKE_REQUIRED_FLAGS "-msse3")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <pmmintrin.h>
int main ()
{
set(CMAKE_REQUIRED_FLAGS "/arch:SSE2")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <emmintrin.h>
int main ()
{
set(CMAKE_REQUIRED_FLAGS "/arch:SSE")
endif()
- check_cxx_source_runs("
+ check_cxx_source_compiles("
#include <xmmintrin.h>
int main ()
{
option(PCL_NO_PRECOMPILE "Do not precompile PCL code for any point types at all." OFF)
mark_as_advanced(PCL_NO_PRECOMPILE)
-# Enable or Disable the check for SSE optimizations
+# Enable or Disable the check for SSE and AVX optimizations
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
+option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." OFF)
+option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." OFF)
+else()
option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." ON)
-mark_as_advanced(PCL_ENABLE_SSE)
-
-# Enable or Disable the check for AVX optimizations
option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON)
+endif()
+mark_as_advanced(PCL_ENABLE_SSE)
mark_as_advanced(PCL_ENABLE_AVX)
if(UNIX)
//boost::fusion::at_key<Key> (p2_) = boost::fusion::at_key<Key> (p1_);
using InT = typename pcl::traits::datatype<PointInT, Key>::type;
using OutT = typename pcl::traits::datatype<PointOutT, Key>::type;
- // Note: don't currently support different types for the same field (e.g. converting double to float)
- BOOST_MPL_ASSERT_MSG ((std::is_same<InT, OutT>::value),
- POINT_IN_AND_POINT_OUT_HAVE_DIFFERENT_TYPES_FOR_FIELD,
- (Key, PointInT&, InT, PointOutT&, OutT));
- memcpy (reinterpret_cast<std::uint8_t*>(&p2_) + pcl::traits::offset<PointOutT, Key>::value,
- reinterpret_cast<const std::uint8_t*>(&p1_) + pcl::traits::offset<PointInT, Key>::value,
- sizeof (InT));
+ *reinterpret_cast<OutT*>(reinterpret_cast<std::uint8_t*>(&p2_) + pcl::traits::offset<PointOutT, Key>::value) =
+ *reinterpret_cast<const InT*>(reinterpret_cast<const std::uint8_t*>(&p1_) + pcl::traits::offset<PointInT, Key>::value);
}
private:
//[0 , 1 ]
Eigen::Matrix<Scalar, 4, 4> transform = Eigen::Matrix<Scalar, 4, 4>::Identity();
transform.template topLeftCorner<3, 3>() = obb_rotational_matrix.transpose();
- transform.template topRightCorner<3, 1>() =-transform.template topLeftCorner<3, 3>()*centroid;
+ transform.template topRightCorner<3, 1>().noalias() =-transform.template topLeftCorner<3, 3>()*centroid;
//when Scalar==double on a Windows 10 machine and MSVS:
//if you substitute the following Scalars with floats you get a 20% worse processing time, if with 2 PointT 55% worse
obb_dimensions(1) = obb_max_pointy - obb_min_pointy;
obb_dimensions(2) = obb_max_pointz - obb_min_pointz;
- obb_center = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud
+ obb_center.noalias() = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud
return (point_count);
}
//[0 , 1 ]
Eigen::Matrix<Scalar, 4, 4> transform = Eigen::Matrix<Scalar, 4, 4>::Identity();
transform.template topLeftCorner<3, 3>() = obb_rotational_matrix.transpose();
- transform.template topRightCorner<3, 1>() =-transform.template topLeftCorner<3, 3>()*centroid;
+ transform.template topRightCorner<3, 1>().noalias() =-transform.template topLeftCorner<3, 3>()*centroid;
//when Scalar==double on a Windows 10 machine and MSVS:
//if you substitute the following Scalars with floats you get a 20% worse processing time, if with 2 PointT 55% worse
obb_dimensions(1) = obb_max_pointy - obb_min_pointy;
obb_dimensions(2) = obb_max_pointz - obb_min_pointz;
- obb_center = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud
+ obb_center.noalias() = centroid + obb_rotational_matrix * shift;//position of the OBB center in the same reference Oxyz of the point cloud
return (point_count);
}
// Identity matrix = transform to CS2 to CS3
// Note: if CS1 == CS2 --> transformation = T3
transformation = Eigen::Transform<Scalar, 3, Eigen::Affine>::Identity ();
- transformation.linear () = T3.linear () * T2.linear ().inverse ();
- transformation.translation () = to0 - (transformation.linear () * fr0);
+ transformation.linear ().noalias () = T3.linear () * T2.linear ().inverse ();
+ transformation.translation ().noalias () = to0 - (transformation.linear () * fr0);
return (true);
}
eigenvectors_.col(2) = eigenvectors_.col(0).cross(eigenvectors_.col(1));
// If not basis only then compute the coefficients
if (!basis_only_)
- coefficients_ = eigenvectors_.transpose() * cloud_demean.topRows<3> ();
+ coefficients_.noalias() = eigenvectors_.transpose() * cloud_demean.topRows<3> ();
compute_done_ = true;
return (true);
}
PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::project] PCA initCompute failed");
Eigen::Vector3f demean_input = input.getVector3fMap () - mean_.head<3> ();
- projection.getVector3fMap () = eigenvectors_.transpose() * demean_input;
+ projection.getVector3fMap ().noalias () = eigenvectors_.transpose() * demean_input;
}
//std::cout << "Cholesky took "<< (choleskyStartTime+get_time ())*1000<<"ms.\n";
//double invStartTime=-get_time ();
- parameters = A.inverse () * b;
+ parameters.noalias() = A.inverse () * b;
//std::cout << "Inverse took "<< (invStartTime+get_time ())*1000<<"ms.\n";
//std::cout << PVARC (A)<<PVARC (b)<<PVARN (parameters);
if (projection_matrix.coeff (0) < 0)
projection_matrix *= -1.0;
+ // if the bottom row is all zeros, except for the second-to-last element, then scale the whole projection matrix (convention)
+ if(std::abs(eigen_vectors.coeff (96))<1e-7 && std::abs(eigen_vectors.coeff (108))<1e-7 && std::abs(eigen_vectors.coeff (120))>1e-5 && std::abs(eigen_vectors.coeff (132))<1e-7)
+ projection_matrix /= projection_matrix.coeffRef (10);
+
return (residual);
}
PCL_ERROR ("[initCompute] Failed to allocate %lu indices.\n", input_->size ());
return (false);
}
- for (auto i = indices_size; i < indices_->size (); ++i) { (*indices_)[i] = static_cast<int>(i); }
+ for (auto i = indices_size; i < indices_->size (); ++i) { (*indices_)[i] = i; }
}
return (true);
#include <pcl/types.h>
#include <pcl/console/print.h> // for PCL_WARN
+#include <cassert> // for assert
#include <utility>
#include <vector>
//thrust::counting_iterator<int> first (0);
// Input: Point Cloud, Indices
// Output: Hypotheses
- transform (//first, first + max_iterations,
+ thrust::transform (//first, first + max_iterations,
//index_sequence_begin,
//index_sequence_begin + max_iterations,
randoms.begin (), randoms.begin () + max_iterations,
//thrust::counting_iterator<int> first (0);
// Input: Point Cloud, Indices
// Output: Hypotheses
- transform (//first, first + max_iterations,
+ thrust::transform (//first, first + max_iterations,
//index_sequence_begin,
//index_sequence_begin + max_iterations,
randoms.begin (), randoms.begin () + max_iterations,
coefficients.z = model_coefficients[2];
coefficients.w = model_coefficients[3];
- return (int) count_if (
+ return (int) thrust::count_if (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
indices_->size (),
{
// pcl::ScopeTime t ("transform");
// Send the data to the device
- transform (
+ thrust::transform (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
nr_points,
{
// pcl::ScopeTime t ("transform");
// Send the data to the device
- transform (
+ thrust::transform (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
nr_points,
coefficients.z = model_coefficients[2];
coefficients.w = model_coefficients[3];
- return (int) count_if (
+ return (int) thrust::count_if (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
indices_->size (),
coefficients.w = model_coefficients[3];
// Send the data to the device
- transform (
+ thrust::transform (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
nr_points,
coefficients.w = ((float4)h[idx]).w;
// Send the data to the device
- transform (
+ thrust::transform (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
nr_points,
coefficients.z = ((float4)h[idx]).z;
coefficients.w = ((float4)h[idx]).w;
- transform (
+ thrust::transform (
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())),
make_zip_iterator (make_tuple (input_->points.begin (), indices_->begin ())) +
nr_points,
find_package(PCL 1.7 REQUIRED)
- include_directories(${PCL_INCLUDE_DIRS})
- link_directories(${PCL_LIBRARY_DIRS})
- add_definitions(${PCL_DEFINITIONS})
-
add_executable (dinast_grabber dinast_grabber.cpp)
target_link_libraries (dinast_grabber ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
- include_directories(${PCL_INCLUDE_DIRS})
- link_directories(${PCL_LIBRARY_DIRS})
- add_definitions(${PCL_DEFINITIONS})
-
add_executable(pcl_hdl_viewer_simple hdl_viewer_simple.cpp)
target_link_libraries(pcl_hdl_viewer_simple ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED COMPONENTS io registration segmentation visualization)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (alignment_prerejective alignment_prerejective.cpp)
target_link_libraries (alignment_prerejective ${PCL_LIBRARIES})
find_package(PCL 1.7.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (bare_earth bare_earth.cpp)
target_link_libraries (bare_earth ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (bspline_fitting bspline_fitting.cpp)
target_link_libraries (bspline_fitting ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (cloud_viewer cloud_viewer.cpp)
target_link_libraries (cloud_viewer ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (cluster_extraction cluster_extraction.cpp)
target_link_libraries (cluster_extraction ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (concatenate_clouds concatenate_clouds.cpp)
target_link_libraries (concatenate_clouds ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (concatenate_fields concatenate_fields.cpp)
target_link_libraries (concatenate_fields ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (concatenate_points concatenate_points.cpp)
target_link_libraries (concatenate_points ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (concave_hull_2d concave_hull_2d.cpp)
target_link_libraries (concave_hull_2d ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (conditional_euclidean_clustering conditional_euclidean_clustering.cpp)
target_link_libraries (conditional_euclidean_clustering ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (conditional_removal conditional_removal.cpp)
target_link_libraries (conditional_removal ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (convex_hull_2d convex_hull_2d.cpp)
target_link_libraries (convex_hull_2d ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (correspondence_grouping correspondence_grouping.cpp)
target_link_libraries (correspondence_grouping ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (cylinder_segmentation cylinder_segmentation.cpp)
target_link_libraries (cylinder_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.8.0 REQUIRED)\r
find_package(OpenCV REQUIRED)\r
\r
-include_directories(${PCL_INCLUDE_DIRS})\r
-link_directories(${PCL_LIBRARY_DIRS})\r
-add_definitions(${PCL_DEFINITIONS})\r
\r
add_executable(davidsdk_images_viewer davidsdk_images_viewer.cpp)\r
target_link_libraries(davidsdk_images_viewer ${PCL_LIBRARIES} ${OpenCV_LIBS})\r
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (don_segmentation don_segmentation.cpp)
target_link_libraries (don_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.8.0 REQUIRED)
find_package(OpenCV REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable(ensenso_cloud_images_viewer ensenso_cloud_images_viewer.cpp)
target_link_libraries(ensenso_cloud_images_viewer ${PCL_LIBRARIES} ${OpenCV_LIBS})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (extract_indices extract_indices.cpp)
target_link_libraries (extract_indices ${PCL_LIBRARIES})
add_executable (sphere_removal sphere_removal.cpp)
target_link_libraries (sphere_removal ${PCL_LIBRARIES})
-add_definitions(${PCL_DEFINITIONS})
#Pcl
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (global_hypothesis_verification global_hypothesis_verification.cpp)
target_link_libraries (global_hypothesis_verification ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
#Searching CUDA
find_package(CUDA)
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (greedy_projection greedy_projection.cpp)
target_link_libraries (greedy_projection ${PCL_LIBRARIES})
project(ground_based_rgbd_people_detector)
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (ground_based_rgbd_people_detector MACOSX_BUNDLE src/main_ground_based_people_detection.cpp)
target_link_libraries (ground_based_rgbd_people_detector ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS} include)
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
+include_directories(include)
add_executable (iccv2011_capture_tool src/capture_tool.cpp src/openni_capture.cpp)
target_link_libraries (iccv2011_capture_tool ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
set(CMAKE_BUILD_TYPE Release)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
add_executable (implicit_shape_model implicit_shape_model.cpp)
target_link_libraries (implicit_shape_model ${PCL_LIBRARIES})
\r
find_package(PCL 1.5 REQUIRED)\r
\r
-include_directories(${PCL_INCLUDE_DIRS})\r
-link_directories(${PCL_LIBRARY_DIRS})\r
-add_definitions(${PCL_DEFINITIONS})\r
\r
add_executable (interactive_icp interactive_icp.cpp)\r
target_link_libraries (interactive_icp ${PCL_LIBRARIES})\r
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS} include)
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
+include_directories(include)
add_executable (iros2011_capture_tool src/capture_tool.cpp src/openni_capture.cpp)
target_link_libraries (iros2011_capture_tool ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (iterative_closest_point iterative_closest_point.cpp)
target_link_libraries (iterative_closest_point ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (kdtree_search kdtree_search.cpp)
target_link_libraries (kdtree_search ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (matrix_transform matrix_transform.cpp)
target_link_libraries (matrix_transform ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (min_cut_segmentation min_cut_segmentation.cpp)
target_link_libraries (min_cut_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (model_outlier_removal model_outlier_removal.cpp)
target_link_libraries (model_outlier_removal ${PCL_LIBRARIES})
find_package(PCL 1.8 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (moment_of_inertia moment_of_inertia.cpp)
target_link_libraries (moment_of_inertia ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (narf_descriptor_visualization narf_descriptor_visualization.cpp)
target_link_libraries (narf_descriptor_visualization ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (narf_feature_extraction narf_feature_extraction.cpp)
target_link_libraries (narf_feature_extraction ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (narf_keypoint_extraction narf_keypoint_extraction.cpp)
target_link_libraries (narf_keypoint_extraction ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable(normal_distributions_transform normal_distributions_transform.cpp)
target_link_libraries (normal_distributions_transform ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (normal_estimation_using_integral_images normal_estimation_using_integral_images.cpp)
target_link_libraries (normal_estimation_using_integral_images ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (octree_change_detection octree_change_detection.cpp)
target_link_libraries (octree_change_detection ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (octree_search octree_search.cpp)
target_link_libraries (octree_search ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (openni_grabber openni_grabber.cpp)
target_link_libraries (openni_grabber ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (openni_narf_keypoint_extraction openni_narf_keypoint_extraction.cpp)
target_link_libraries (openni_narf_keypoint_extraction ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (openni_range_image_visualization openni_range_image_visualization.cpp)
target_link_libraries (openni_range_image_visualization ${PCL_LIBRARIES})
find_package(PCL 1.4 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (pairwise_incremental_registration pairwise_incremental_registration.cpp)
target_link_libraries (pairwise_incremental_registration ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (passthrough passthrough.cpp)
target_link_libraries (passthrough ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (pcd_read pcd_read.cpp)
target_link_libraries (pcd_read ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (pcd_write pcd_write.cpp)
target_link_libraries (pcd_write ${PCL_LIBRARIES})
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(pcl_painter2D_demo)
find_package(PCL 1.7)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
add_executable(pcl_painter2D_demo pcl_painter2D_demo.cpp)
target_link_libraries(pcl_painter2D_demo ${PCL_LIBRARIES})
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(pcl_plotter)
find_package(PCL 1.7 REQUIRED COMPONENTS common visualization)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
add_executable(pcl_plotter pcl_plotter_demo.cpp)
target_link_libraries(pcl_plotter ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (pcl_visualizer_demo pcl_visualizer_demo.cpp)
target_link_libraries (pcl_visualizer_demo ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (planar_segmentation planar_segmentation.cpp)
target_link_libraries (planar_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (point_cloud_compression point_cloud_compression.cpp)
target_link_libraries (point_cloud_compression ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (project_inliers project_inliers.cpp)
target_link_libraries (project_inliers ${PCL_LIBRARIES})
# Fix a compilation bug under ubuntu 16.04 (Xenial)
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
-include_directories(${PCL_INCLUDE_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
set(project_SOURCES main.cpp pclviewer.cpp)
add_executable(${PROJECT_NAME} ${project_SOURCES})
# Fix a compilation bug under ubuntu 16.04 (Xenial)
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
-include_directories(${PCL_INCLUDE_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
set(project_SOURCES main.cpp pclviewer.cpp)
add_executable(${PROJECT_NAME} ${project_SOURCES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (radius_outlier_removal radius_outlier_removal.cpp)
target_link_libraries (radius_outlier_removal ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (random_sample_consensus random_sample_consensus.cpp)
target_link_libraries (random_sample_consensus ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (range_image_border_extraction range_image_border_extraction.cpp)
target_link_libraries (range_image_border_extraction ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (range_image_creation range_image_creation.cpp)
target_link_libraries (range_image_creation ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (range_image_visualization range_image_visualization.cpp)
target_link_libraries (range_image_visualization ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (region_growing_rgb_segmentation region_growing_rgb_segmentation.cpp)
target_link_libraries (region_growing_rgb_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.5 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (region_growing_segmentation region_growing_segmentation.cpp)
target_link_libraries (region_growing_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.3 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
#add_executable (example1 example1.cpp)
#target_link_libraries (example1 ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (remove_outliers remove_outliers.cpp)
target_link_libraries (remove_outliers ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (resampling resampling.cpp)
target_link_libraries (resampling ${PCL_LIBRARIES})
find_package(PCL 1.8 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (rops_feature rops_feature.cpp)
target_link_libraries (rops_feature ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (statistical_removal statistical_removal.cpp)
target_link_libraries (statistical_removal ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (stick_segmentation stick_segmentation.cpp)
target_link_libraries (stick_segmentation ${PCL_LIBRARIES})
find_package(PCL 1.8 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (supervoxel_clustering supervoxel_clustering.cpp)
target_link_libraries (supervoxel_clustering ${PCL_LIBRARIES})
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (template_alignment template_alignment.cpp)
target_link_libraries (template_alignment ${PCL_LIBRARIES})
find_package(PCL 1.7 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (tracking_sample tracking_sample.cpp)
target_link_libraries (tracking_sample ${PCL_LIBRARIES})
project(vfh_cluster_classifier)
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
find_package(HDF5 REQUIRED)
find_package(FLANN REQUIRED)
find_package(PCL 1.2 REQUIRED)
-include_directories(${PCL_INCLUDE_DIRS})
-link_directories(${PCL_LIBRARY_DIRS})
-add_definitions(${PCL_DEFINITIONS})
-
add_executable (voxel_grid voxel_grid.cpp)
target_link_libraries (voxel_grid ${PCL_LIBRARIES})
.. code-block:: cmake
- cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(MY_GRAND_PROJECT)
find_package(PCL 1.3 REQUIRED)
- include_directories(${PCL_INCLUDE_DIRS})
- link_directories(${PCL_LIBRARY_DIRS})
- add_definitions(${PCL_DEFINITIONS})
add_executable(pcd_write_test pcd_write.cpp)
target_link_libraries(pcd_write_test ${PCL_LIBRARIES})
.. code-block:: cmake
- cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
This is mandatory for cmake, and since we are making a very basic
project we don't need features from cmake 2.8 or higher.
* several: find_package(PCL 1.3 REQUIRED COMPONENTS io common)
* all existing: find_package(PCL 1.3 REQUIRED)
-.. code-block:: cmake
-
- include_directories(${PCL_INCLUDE_DIRS})
- link_directories(${PCL_LIBRARY_DIRS})
- add_definitions(${PCL_DEFINITIONS})
-
-When PCL is found, several related variables are set:
-
-* `PCL_FOUND`: set to 1 if PCL is found, otherwise unset
-* `PCL_INCLUDE_DIRS`: set to the paths to PCL installed headers and
- the dependency headers
-* `PCL_LIBRARIES`: set to the file names of the built and installed PCL libraries
-* `PCL_LIBRARY_DIRS`: set to the paths to where PCL libraries and 3rd
- party dependencies reside
-* `PCL_VERSION`: the version of the found PCL
-* `PCL_COMPONENTS`: lists all available components
-* `PCL_DEFINITIONS`: lists the needed preprocessor definitions and compiler flags
-
-To let cmake know about external headers you include in your project,
-one needs to use ``include_directories()`` macro. In our case
-``PCL_INCLUDE_DIRS``, contains exactly what we need, thus we ask cmake
-to search the paths it contains for a header potentially included.
-
.. code-block:: cmake
add_executable(pcd_write_test pcd_write.cpp)
yourself. When you are using such targets they are called `imported
targets` and act just like any other target.
+CMake variables defined after finding PCL
+=========================================
+
+When PCL is found, several related variables are set:
+
+* `PCL_FOUND`: set to 1 if PCL is found, otherwise unset
+* `PCL_INCLUDE_DIRS`: set to the paths to PCL installed headers and
+ the dependency headers
+* `PCL_LIBRARIES`: set to the file names of the built and installed PCL libraries
+* `PCL_LIBRARY_DIRS`: set to the paths to where PCL libraries and 3rd
+ party dependencies reside
+* `PCL_VERSION`: the version of the found PCL
+* `PCL_COMPONENTS`: lists all available components
+* `PCL_DEFINITIONS`: lists the needed preprocessor definitions and compiler flags
+
+In older PCL versions, it was necessary to explicitly tell CMake about `PCL_INCLUDE_DIRS`, `PCL_LIBRARY_DIRS`, and `PCL_DEFINITIONS`, but in newer PCL versions, the `target_link_libraries` call handles that automatically.
+
Compiling and running the project
---------------------------------
+#include <chrono>
#include <thread>
#include <pcl/stereo/stereo_matching.h>
"include/pcl/${SUBSYS_NAME}/impl/range_image_border_extractor.hpp"
)
+# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically!
set(srcs
+ src/integral_image_normal.cpp
+ src/shot.cpp
+ src/3dsc.cpp
+ src/multiscale_feature_persistence.cpp
+ src/vfh.cpp
src/board.cpp
src/flare.cpp
src/brisk_2d.cpp
src/from_meshes.cpp
src/gasd.cpp
src/gfpfh.cpp
- src/integral_image_normal.cpp
src/intensity_gradient.cpp
src/intensity_spin.cpp
src/linear_least_squares_normal.cpp
src/moment_invariants.cpp
src/moment_of_inertia_estimation.cpp
- src/multiscale_feature_persistence.cpp
src/narf.cpp
src/normal_3d.cpp
src/normal_based_signature.cpp
src/organized_edge_detection.cpp
src/pfh.cpp
src/ppf.cpp
- src/shot.cpp
src/shot_lrf.cpp
src/spin_image.cpp
src/principal_curvatures.cpp
src/rsd.cpp
src/grsd.cpp
src/statistical_multiscale_interest_region_extraction.cpp
- src/vfh.cpp
src/esf.cpp
- src/3dsc.cpp
src/usc.cpp
src/range_image_border_extractor.cpp
)
// Check if a space search locator was given
if (!tree_)
{
- if (surface_->isOrganized () && input_->isOrganized ())
+ if (surface_->isOrganized () && input_->isOrganized ()) {
tree_.reset (new pcl::search::OrganizedNeighbor<PointInT> ());
- else
+ if(!tree_->setInputCloud (surface_)) { // may return false if OrganizedNeighbor cannot work with the cloud, then use KdTree instead
+ tree_.reset (new pcl::search::KdTree<PointInT> (false));
+ }
+ } else {
tree_.reset (new pcl::search::KdTree<PointInT> (false));
+ }
}
- if (tree_->getInputCloud () != surface_) // Make sure the tree searches the surface
- tree_->setInputCloud (surface_);
+ if (tree_->getInputCloud () != surface_) { // Make sure the tree searches the surface
+ if(!tree_->setInputCloud (surface_)) {
+ PCL_ERROR ("[pcl::%s::compute] The given search method cannot work with the given input cloud/search surface.\n", getClassName ().c_str ());
+ return (false);
+ }
+ }
// Do a fast check to see if the search parameters are well defined
SignedDistanceT best_shape_score = -std::numeric_limits<SignedDistanceT>::max ();
int best_shape_index = -1;
- Eigen::Vector3f best_margin_point;
-
const float radius2 = tangent_radius_ * tangent_radius_;
const float margin_distance2 = margin_thresh_ * margin_thresh_ * radius2;
for (unsigned int i = 0; i < (width_ + 1); ++i)
so_previous_row[i].setZero();
- SecondOrderType so_element;
for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
previous_row = current_row, current_row += (width_ + 1),
count_previous_row = count_current_row, count_current_row += (width_ + 1),
// std::cout << A << "\n*\n" << bb << "\n=\n" << x << "\nvs.\n" << x2 << "\n\n";
// std::cout << A * x << "\nvs.\n" << A * x2 << "\n\n------\n";
// Project the gradient vector, x, onto the tangent plane
- gradient = (Eigen::Matrix3f::Identity () - normal*normal.transpose ()) * x;
+ gradient.noalias() = (Eigen::Matrix3f::Identity () - normal*normal.transpose ()) * x;
}
//////////////////////////////////////////////////////////////////////////////////////////////
obb_max_point_.y -= shift (1);
obb_max_point_.z -= shift (2);
- obb_position_ = mean_value_ + obb_rotational_matrix_ * shift;
+ obb_position_.noalias() = mean_value_ + obb_rotational_matrix_ * shift;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
current_point (1) = (*input_)[(*indices_)[i_point]].y - mean_value_ (1);
current_point (2) = (*input_)[(*indices_)[i_point]].z - mean_value_ (2);
- covariance_matrix += current_point * current_point.transpose ();
+ covariance_matrix.noalias() += current_point * current_point.transpose ();
}
covariance_matrix *= factor;
current_point (1) = (*cloud)[i_point].y - mean_value_ (1);
current_point (2) = (*cloud)[i_point].z - mean_value_ (2);
- covariance_matrix += current_point * current_point.transpose ();
+ covariance_matrix.noalias() += current_point * current_point.transpose ();
}
covariance_matrix *= factor;
Eigen::Vector3f& major_axis, Eigen::Vector3f& middle_axis, Eigen::Vector3f& minor_axis, float& major_value,
float& middle_value, float& minor_value)
{
- Eigen::EigenSolver <Eigen::Matrix <float, 3, 3> > eigen_solver;
- eigen_solver.compute (covariance_matrix);
+ const Eigen::SelfAdjointEigenSolver<Eigen::Matrix<float, 3, 3>> eigen_solver(covariance_matrix);
- Eigen::EigenSolver <Eigen::Matrix <float, 3, 3> >::EigenvectorsType eigen_vectors;
- Eigen::EigenSolver <Eigen::Matrix <float, 3, 3> >::EigenvalueType eigen_values;
- eigen_vectors = eigen_solver.eigenvectors ();
- eigen_values = eigen_solver.eigenvalues ();
+ const Eigen::SelfAdjointEigenSolver <Eigen::Matrix <float, 3, 3> >::EigenvectorsType& eigen_vectors = eigen_solver.eigenvectors ();
+ const Eigen::SelfAdjointEigenSolver <Eigen::Matrix <float, 3, 3> >::RealVectorType& eigen_values = eigen_solver.eigenvalues ();
unsigned int temp = 0;
unsigned int major_index = 0;
unsigned int middle_index = 1;
unsigned int minor_index = 2;
- if (eigen_values.real () (major_index) < eigen_values.real () (middle_index))
+ if (eigen_values (major_index) < eigen_values (middle_index))
{
temp = major_index;
major_index = middle_index;
middle_index = temp;
}
- if (eigen_values.real () (major_index) < eigen_values.real () (minor_index))
+ if (eigen_values (major_index) < eigen_values (minor_index))
{
temp = major_index;
major_index = minor_index;
minor_index = temp;
}
- if (eigen_values.real () (middle_index) < eigen_values.real () (minor_index))
+ if (eigen_values (middle_index) < eigen_values (minor_index))
{
temp = minor_index;
minor_index = middle_index;
middle_index = temp;
}
- major_value = eigen_values.real () (major_index);
- middle_value = eigen_values.real () (middle_index);
- minor_value = eigen_values.real () (minor_index);
+ major_value = eigen_values (major_index);
+ middle_value = eigen_values (middle_index);
+ minor_value = eigen_values (minor_index);
- major_axis = eigen_vectors.col (major_index).real ();
- middle_axis = eigen_vectors.col (middle_index).real ();
- minor_axis = eigen_vectors.col (minor_index).real ();
+ major_axis = eigen_vectors.col (major_index);
+ middle_axis = eigen_vectors.col (middle_index);
+ minor_axis = eigen_vectors.col (minor_index);
major_axis.normalize ();
middle_axis.normalize ();
scatter /= sum_w;
- Eigen::JacobiSVD <Eigen::MatrixXf> svd (scatter, Eigen::ComputeFullV);
+ const Eigen::JacobiSVD <Eigen::Matrix3f> svd (scatter, Eigen::ComputeFullV);
Eigen::Vector3f evx = svd.matrixV ().col (0);
Eigen::Vector3f evy = svd.matrixV ().col (1);
Eigen::Vector3f evz = svd.matrixV ().col (2);
for (std::size_t idx = 0; idx < indices.size(); ++idx)
{
const auto normal = normals[indices[idx]].getNormalVector3fMap();
- projected_normals[idx] = M * normal;
+ projected_normals[idx].noalias() = M * normal;
xyz_centroid += projected_normals[idx];
}
for (const auto &i_pt : pt)
{
Eigen::Vector3f vec = i_pt - feature_point;
- curr_scatter_matrix += vec * (vec.transpose ());
+ curr_scatter_matrix.noalias() += vec * (vec.transpose ());
for (const auto &j_pt : pt)
- curr_scatter_matrix += vec * ((j_pt - feature_point).transpose ());
+ curr_scatter_matrix.noalias() += vec * ((j_pt - feature_point).transpose ());
}
scatter_matrices.emplace_back (coeff * curr_scatter_matrix);
}
pcl::ROPSEstimation <PointInT, PointOutT>::computeEigenVectors (const Eigen::Matrix3f& matrix,
Eigen::Vector3f& major_axis, Eigen::Vector3f& middle_axis, Eigen::Vector3f& minor_axis) const
{
- Eigen::EigenSolver <Eigen::Matrix3f> eigen_solver;
- eigen_solver.compute (matrix);
+ Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(matrix, Eigen::ComputeEigenvectors);
- Eigen::EigenSolver <Eigen::Matrix3f>::EigenvectorsType eigen_vectors;
- Eigen::EigenSolver <Eigen::Matrix3f>::EigenvalueType eigen_values;
- eigen_vectors = eigen_solver.eigenvectors ();
- eigen_values = eigen_solver.eigenvalues ();
+ const Eigen::SelfAdjointEigenSolver <Eigen::Matrix3f>::EigenvectorsType& eigen_vectors = eigen_solver.eigenvectors ();
+ const Eigen::SelfAdjointEigenSolver <Eigen::Matrix3f>::RealVectorType& eigen_values = eigen_solver.eigenvalues ();
unsigned int temp = 0;
unsigned int major_index = 0;
unsigned int middle_index = 1;
unsigned int minor_index = 2;
- if (eigen_values.real () (major_index) < eigen_values.real () (middle_index))
+ if (eigen_values (major_index) < eigen_values (middle_index))
{
temp = major_index;
major_index = middle_index;
middle_index = temp;
}
- if (eigen_values.real () (major_index) < eigen_values.real () (minor_index))
+ if (eigen_values (major_index) < eigen_values (minor_index))
{
temp = major_index;
major_index = minor_index;
minor_index = temp;
}
- if (eigen_values.real () (middle_index) < eigen_values.real () (minor_index))
+ if (eigen_values (middle_index) < eigen_values (minor_index))
{
temp = minor_index;
minor_index = middle_index;
middle_index = temp;
}
- major_axis = eigen_vectors.col (major_index).real ();
- middle_axis = eigen_vectors.col (middle_index).real ();
- minor_axis = eigen_vectors.col (minor_index).real ();
+ major_axis = eigen_vectors.col (major_index);
+ middle_axis = eigen_vectors.col (middle_index);
+ minor_axis = eigen_vectors.col (minor_index);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
distance = search_parameter_ - sqrt (n_sqr_distances[i_idx]);
// Multiply vij * vij'
- cov_m += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ());
+ cov_m.noalias() += distance * (vij.row (valid_nn_points).head<3> ().transpose () * vij.row (valid_nn_points).head<3> ());
sum += distance;
valid_nn_points++;
#pragma omp parallel for \
default(none) \
shared(output) \
- num_threads(threads_)
+ num_threads(threads_) \
+ schedule(dynamic, 64)
for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t> (indices_->size ()); ++i)
{
// point result
homMatrix = transformPC.matrix ();
Eigen::Matrix4f trans_copy = trans.inverse ();
- trans = trans_copy * center_mat * homMatrix;
+ trans.noalias() = trans_copy * center_mat * homMatrix;
return trans;
}
return()
endif()
+# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically!
set(srcs
+ src/voxel_grid_covariance.cpp
src/conditional_removal.cpp
src/convolution.cpp
src/crop_box.cpp
src/fast_bilateral.cpp
src/fast_bilateral_omp.cpp
src/crop_hull.cpp
- src/voxel_grid_covariance.cpp
src/voxel_grid_label.cpp
src/frustum_culling.cpp
src/covariance_sampling.cpp
inline void
transformComparison (const Eigen::Matrix4f &transform)
{
- tf_comp_matr_ = transform.transpose () * comp_matr_ * transform;
- tf_comp_vect_ = comp_vect_.transpose () * transform;
+ tf_comp_matr_.noalias() = transform.transpose () * comp_matr_ * transform;
+ tf_comp_vect_.noalias() = comp_vect_.transpose () * transform;
}
/** \brief transform the coordinate system of the comparison. If you think of
* \param[in] sigma
*/
inline void
- setSigma (float sigma) { sigma_ = sigma; }
+ setSigma (float sigma) { sigma_ = sigma; sigma_sqr_ = sigma_ * sigma_; }
/** Set the distance threshold relative to a sigma factor i.e. points such as
* ||pi - q|| > sigma_coefficient^2 * sigma^2 are not considered.
#define PCL_FILTERS_IMPL_FAST_VOXEL_GRID_H_
#include <pcl/common/io.h>
+#include <pcl/common/point_tests.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <boost/mpl/size.hpp> // for size
std::size_t op = 0; // output pointer
for (const auto& point: *input_)
{
+ if(!pcl::isXYZFinite(point))
+ continue;
int ix = static_cast<int> (std::floor (point.x * inverse_leaf_size_[0]));
int iy = static_cast<int> (std::floor (point.y * inverse_leaf_size_[1]));
int iz = static_cast<int> (std::floor (point.z * inverse_leaf_size_[2]));
output.resize (op);
output.width = output.size ();
output.height = 1; // downsampling breaks the organized structure
- output.is_dense = false; // we filter out invalid points
+ output.is_dense = true; // we filter out invalid points
}
#define PCL_INSTANTIATE_ApproximateVoxelGrid(T) template class PCL_EXPORTS pcl::ApproximateVoxelGrid<T>;
}
// Compute the covariance matrix C and its 6 eigenvectors (initially complex, move them to a double matrix)
- covariance_matrix = f_mat * f_mat.transpose ();
+ covariance_matrix.noalias() = f_mat * f_mat.transpose ();
return true;
}
template<typename PointT> void
pcl::FarthestPointSampling<PointT>::applyFilter (Indices &indices)
{
- const std::size_t size = input_->size();
+ const std::size_t size = indices_->size();
//if requested number of point is equal to the point cloud size, copy original cloud
if (sample_size_ == size)
{
std::mt19937 random_gen(seed_);
std::uniform_int_distribution<index_t> dis(0, size -1);
+ //lambda to map filter indices back to pointcloud indices for increased readability
+ auto toCloudIndex = [this](const auto idx){return (*indices_)[idx];};
+
//pick the first point at random
index_t max_index = dis(random_gen);
distances_to_selected_points[max_index] = -1.0;
- indices.push_back(max_index);
+ indices.push_back(toCloudIndex(max_index));
for (std::size_t j = 1; j < sample_size_; ++j)
{
index_t next_max_index = 0;
- const PointT& max_index_point = (*input_)[max_index];
+ const PointT& max_index_point = (*input_)[toCloudIndex(max_index)];
//recompute distances
for (std::size_t i = 0; i < size; ++i)
{
if (distances_to_selected_points[i] == -1.0)
continue;
- distances_to_selected_points[i] = std::min(distances_to_selected_points[i], geometry::distance((*input_)[i], max_index_point));
+ distances_to_selected_points[i] = std::min(distances_to_selected_points[i], geometry::distance((*input_)[toCloudIndex(i)], max_index_point));
if (distances_to_selected_points[i] > distances_to_selected_points[next_max_index])
next_max_index = i;
}
//elements are guaranteed to not be selected
max_index = next_max_index;
distances_to_selected_points[max_index] = -1.0;
- indices.push_back(max_index);
+ indices.push_back(toCloudIndex(max_index));
//set distance to -1 to ignore during max element search
}
for (std::size_t k = 0; k < distances_to_selected_points.size(); ++k)
{
if (distances_to_selected_points[k] != -1.0)
- (*removed_indices_).push_back(k);
+ (*removed_indices_).push_back(toCloudIndex(k));
}
}
}
{
PointT &pt_new = output[cp++] = pt;
pt_new.x = pt_new.y = pt_new.z = user_filter_value_;
+ if(!std::isfinite(user_filter_value_))
+ output.is_dense = false;
}
}
// Accumulate point sum for centroid calculation
leaf.mean_ += pt3d;
// Accumulate x*xT for single pass covariance calculation
- leaf.cov_ += pt3d * pt3d.transpose ();
+ leaf.cov_.noalias() += pt3d * pt3d.transpose ();
// Do we need to process all the fields?
if (!downsample_all_data_)
// Accumulate point sum for centroid calculation
leaf.mean_ += pt3d;
// Accumulate x*xT for single pass covariance calculation
- leaf.cov_ += pt3d * pt3d.transpose ();
+ leaf.cov_.noalias() += pt3d * pt3d.transpose ();
// Do we need to process all the fields?
if (!downsample_all_data_)
eigen_val (1, 1) = min_covar_eigvalue;
}
- leaf.cov_ = leaf.evecs_ * eigen_val * leaf.evecs_.inverse ();
+ leaf.cov_.noalias() = leaf.evecs_ * eigen_val * leaf.evecs_.inverse ();
}
leaf.evals_ = eigen_val.diagonal ();
for (int i = 0; i < pnt_per_cell; i++)
{
rand_point = Eigen::Vector3d (var_nor (), var_nor (), var_nor ());
- dist_point = cell_mean + cholesky_decomp * rand_point;
+ dist_point.noalias() = cell_mean + cholesky_decomp * rand_point;
cell_cloud.push_back (PointXYZ (static_cast<float> (dist_point (0)), static_cast<float> (dist_point (1)), static_cast<float> (dist_point (2))));
}
}
result.b = static_cast<std::uint8_t>(b);
return (result);
}
+
+#ifdef _MSC_VER
+// Seems to be necessary with MSVC, but not necessary with other compilers (even produces warning with PCL_SYMBOL_VISIBILITY_HIDDEN and gcc)
+#ifndef PCL_NO_PRECOMPILE
+#include <pcl/impl/instantiate.hpp>
+#include <pcl/point_types.h>
+
+PCL_INSTANTIATE_PRODUCT(
+ Convolution, ((pcl::RGB))((pcl::RGB)))
+
+PCL_INSTANTIATE_PRODUCT(
+ Convolution, ((pcl::PointXYZRGB))((pcl::PointXYZRGB)))
+#endif // PCL_NO_PRECOMPILE
+#endif // _MSC_VER
+
} // namespace filters
} // namespace pcl
prop.multiProcessorCount,
sm_cores,
sm_cores * prop.multiProcessorCount);
+ int clockRate;
+ cudaSafeCall(cudaDeviceGetAttribute(&clockRate, cudaDevAttrClockRate, dev));
printf(" GPU Clock Speed: %.2f GHz\n",
- prop.clockRate * 1e-6f);
+ clockRate * 1e-6f);
// This is not available in the CUDA Runtime API, so we make the necessary calls the
// driver API to support this for output
printf(
" Concurrent copy and execution: %s with %d copy engine(s)\n",
- (prop.deviceOverlap ? "Yes" : "No"),
+ (prop.asyncEngineCount ? "Yes" : "No"),
prop.asyncEngineCount);
+ int kernelExecTimeoutEnabled;
+ cudaSafeCall(cudaDeviceGetAttribute(
+ &kernelExecTimeoutEnabled, cudaDevAttrKernelExecTimeout, dev));
printf(" Run time limit on kernels: %s\n",
- prop.kernelExecTimeoutEnabled ? "Yes" : "No");
+ kernelExecTimeoutEnabled ? "Yes" : "No");
printf(" Integrated GPU sharing Host Memory: %s\n",
prop.integrated ? "Yes" : "No");
printf(" Support host page-locked memory mapping: %s\n",
printf(" Device PCI Bus ID / PCI location ID: %d / %d\n",
prop.pciBusID,
prop.pciDeviceID);
+ int propComputeMode;
+ cudaSafeCall(cudaDeviceGetAttribute(&propComputeMode, cudaDevAttrComputeMode, dev));
printf(" Compute Mode:\n");
- printf(" %s \n", computeMode[prop.computeMode]);
+ printf(" %s \n", computeMode[propComputeMode]);
}
printf("\n");
#include <algorithm>
-namespace pcl
+namespace pcl {
+namespace device {
+struct Info {
+ enum { SIZE = 4 };
+ int data[SIZE];
+};
+
+template <int n>
+struct Point {
+ int data[n];
+};
+
+template <int in, int out, typename Info>
+__global__ void
+deviceCopyFields4B(const Info info, const int size, const void* input, void* output)
{
- namespace device
- {
- struct Info
- {
- enum { SIZE = 4 };
- int data[SIZE];
- };
-
- template<int n>
- struct Point
- {
- int data[n];
- };
-
- template<int in, int out, typename Info>
- __global__ void deviceCopyFields4B(const Info info, const int size, const void* input, void* output)
- {
- int idx = blockIdx.x * blockDim.x + threadIdx.x;
-
- if (idx < size)
- {
- Point<in> point_in = reinterpret_cast<const Point<in>* >( input)[idx];
- Point<out> point_out = reinterpret_cast< Point<out>* >(output)[idx];
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
- for(int i = 0; i < Info::SIZE; ++i)
- {
- int byte;
- int code = info.data[i];
+ if (idx < size) {
+ Point<in> point_in = reinterpret_cast<const Point<in>*>(input)[idx];
+ Point<out> point_out = reinterpret_cast<Point<out>*>(output)[idx];
- byte = ((code >> 0) & 0xFF);
+ for (int i = 0; i < Info::SIZE; ++i) {
+ int byte;
+ int code = info.data[i];
- if (byte == 0xFF)
- break;
- else
- point_out.data[byte >> 4] = point_in.data[byte & 0xF];
+ byte = ((code >> 0) & 0xFF);
- byte = ((code >> 8) & 0xFF);
+ if (byte == 0xFF)
+ break;
+ else
+ point_out.data[byte >> 4] = point_in.data[byte & 0xF];
- if (byte == 0xFF)
- break;
- else
- point_out.data[byte >> 4] = point_in.data[byte & 0xF];
+ byte = ((code >> 8) & 0xFF);
- byte = ((code >> 16) & 0xFF);
+ if (byte == 0xFF)
+ break;
+ else
+ point_out.data[byte >> 4] = point_in.data[byte & 0xF];
- if (byte == 0xFF)
- break;
- else
- point_out.data[byte >> 4] = point_in.data[byte & 0xF];
+ byte = ((code >> 16) & 0xFF);
- byte = ((code >> 24) & 0xFF);
+ if (byte == 0xFF)
+ break;
+ else
+ point_out.data[byte >> 4] = point_in.data[byte & 0xF];
- if (byte == 0xFF)
- break;
- else
- point_out.data[byte >> 4] = point_in.data[byte & 0xF];
- }
+ byte = ((code >> 24) & 0xFF);
- reinterpret_cast< Point<out>* >(output)[idx] = point_out;
- }
- };
+ if (byte == 0xFF)
+ break;
+ else
+ point_out.data[byte >> 4] = point_in.data[byte & 0xF];
+ }
- template<int in_size, int out_size>
- void cf(int info[4], int size, const void* input, void* output)
- {
- Info i;
- std::copy(info, info + 4, i.data);
+ reinterpret_cast<Point<out>*>(output)[idx] = point_out;
+ }
+};
- dim3 block(256);
- dim3 grid(divUp(size, block.x));
+template <int in_size, int out_size>
+void
+cf(int info[4], int size, const void* input, void* output)
+{
+ Info i;
+ std::copy(info, info + 4, i.data);
- deviceCopyFields4B<in_size, out_size><<<grid, block>>>(i, size, input, output);
- cudaSafeCall ( cudaGetLastError () );
- cudaSafeCall (cudaDeviceSynchronize ());
- }
+ dim3 block(256);
+ dim3 grid(divUp(size, block.x));
- using copy_fields_t = void (*)(int info[4], int size, const void* input, void* output);
- }
+ deviceCopyFields4B<in_size, out_size><<<grid, block>>>(i, size, input, output);
+ cudaSafeCall(cudaGetLastError());
+ cudaSafeCall(cudaDeviceSynchronize());
}
-namespace pcl
-{
- namespace gpu
- {
- using namespace pcl::device;
+using copy_fields_t = void (*)(int info[4], int size, const void* input, void* output);
+} // namespace device
+} // namespace pcl
- PCL_EXPORTS void copyFieldsImpl(int in_size, int out_size, int rules[4], int size, const void* input, void* output)
- {
- pcl::device::copy_fields_t funcs[16][16] =
+namespace pcl {
+namespace gpu {
+using namespace pcl::device;
+
+PCL_EXPORTS void
+copyFieldsImpl(
+ int in_size, int out_size, int rules[4], int size, const void* input, void* output)
+{
+ // clang-format off
+ pcl::device::copy_fields_t funcs[16][16] =
{
{ /**/ cf<1,1>, cf<1, 2>, cf<1, 3>, cf<1, 4>, /**/ cf<1, 5>, cf<1, 6>, cf<1, 7>, cf<1, 8>, /**/ cf<1, 9>, cf<1,10>, cf<1, 11>, cf<1, 12>, /**/ cf<1, 13>, cf<1, 14>, cf<1, 15>, cf<1,16> },
{ /**/ cf<2,1>, cf<2, 2>, cf<2, 3>, cf<2, 4>, /**/ cf<2, 5>, cf<2, 6>, cf<2, 7>, cf<2, 8>, /**/ cf<2, 9>, cf<1,10>, cf<2, 11>, cf<2, 12>, /**/ cf<2, 13>, cf<2, 14>, cf<2, 15>, cf<2,16> },
{ /**/ cf<15,1>, cf<15,2>, cf<15,3>, cf<15,4>, /**/ cf<15,5>, cf<15,6>, cf<15,7>, cf<15,8>, /**/ cf<15,9>, cf<1,10>, cf<15,11>, cf<15,12>, /**/ cf<15,13>, cf<15,14>, cf<15,15>, cf<15,16> },
{ /**/ cf<16,1>, cf<16,2>, cf<16,3>, cf<16,4>, /**/ cf<16,5>, cf<16,6>, cf<16,7>, cf<16,8>, /**/ cf<16,9>, cf<1,10>, cf<16,11>, cf<16,12>, /**/ cf<16,13>, cf<16,14>, cf<16,15>, cf<16,16> }
};
-
- funcs[in_size-1][out_size-1](rules, size, input, output);
- }
- }
+ // clang-format on
+ funcs[in_size - 1][out_size - 1](rules, size, input, output);
}
-
+} // namespace gpu
+} // namespace pcl
thrust::device_ptr<PointT> src_beg((PointT*)cloud.ptr());
thrust::device_ptr<PointT> src_end = src_beg + cloud.size();
- centroid = transform_reduce(src_beg, src_beg, PointT2float3<PointT>(), make_float3(0.f, 0.f, 0.f), PlusFloat3());
+ centroid = thrust::transform_reduce(src_beg, src_beg, PointT2float3<PointT>(), make_float3(0.f, 0.f, 0.f), PlusFloat3());
centroid *= 1.f/cloud.size();
}
thrust::device_ptr<int> map_end = map_beg + indices.size();
- centroid = transform_reduce(make_permutation_iterator(src_beg, map_beg),
+ centroid = thrust::transform_reduce(make_permutation_iterator(src_beg, map_beg),
make_permutation_iterator(src_beg, map_end),
PointT2float3<PointT>(), make_float3(0.f, 0.f, 0.f), PlusFloat3());
thrust::maximum<thrust::tuple<float, int>> op;
thrust::tuple<float, int> res =
- transform_reduce(
+ thrust::transform_reduce(
make_zip_iterator(make_tuple( src_beg, cf )),
make_zip_iterator(make_tuple( src_beg, ce )),
TupleDistCvt(pivot), init, op);
thrust::tuple<float, int> init(0.f, 0);
thrust::maximum<thrust::tuple<float, int>> op;
- thrust::tuple<float, int> res = transform_reduce(
+ thrust::tuple<float, int> res = thrust::transform_reduce(
make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_beg), cf )),
make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_end), ce )),
TupleDistCvt(pivot), init, op);
#include "pcl/gpu/utils/safe_call.hpp"
#include "pcl/gpu/utils/device/warp.hpp"
#include "pcl/gpu/utils/device/functional.hpp"
-#include "pcl/gpu/utils/device/funcattrib.hpp"
-#include "pcl/gpu/utils/timers_cuda.hpp"
#include "pcl/gpu/features/device/pair_features.hpp"
-#include <iostream>
-
using namespace pcl::gpu;
using namespace pcl::device;
float hist_incr = 100.f / (float)(size - 1); // or 100/(size - 1) ???
- //now [inds, inds + size) contains indices of neighb points for idx-th point in cloud
+ //now [inds, inds + size) contains indices of neighboring points for idx-th point in cloud
//this list also contains idx itseelf.
for(int i = lane; i < size; i += Warp::STRIDE)
#define PCL_DEVICE_FUNCTIONAL_HPP_
#include <thrust/functional.h>
+#include <cuda.h>
namespace pcl
{
namespace device
{
- // Function Objects
-
- using thrust::binary_function;
// Arithmetic Operations
// Generalized Identity Operations
- using thrust::identity;
+ #if CUDA_VERSION >= 13000
+ using cuda::std::identity;
+ #else
+ using thrust::identity;
+ #endif
using thrust::project1st;
using thrust::project2nd;
PointT& point = (*outputCloud_arg)[beginIdx_arg + i];
// decode point position
- point.x = static_cast<float> (referencePoint_arg[0] + diffX * pointCompressionResolution_);
- point.y = static_cast<float> (referencePoint_arg[1] + diffY * pointCompressionResolution_);
- point.z = static_cast<float> (referencePoint_arg[2] + diffZ * pointCompressionResolution_);
+ point.x = static_cast<float> (referencePoint_arg[0] + (diffX+0.5) * pointCompressionResolution_);
+ point.y = static_cast<float> (referencePoint_arg[1] + (diffY+0.5) * pointCompressionResolution_);
+ point.z = static_cast<float> (referencePoint_arg[2] + (diffZ+0.5) * pointCompressionResolution_);
}
}
const std::string &cloud_name = "cloud")
{
pcl::PCLPointCloud2 blob;
- pcl::toPCLPointCloud2<PointT> (cloud, blob);
+ pcl::toPCLPointCloud2<PointT> (cloud, blob, false); // no padding
return (write (file_name, blob, cloud_name));
}
};
{
for (std::size_t i = 0; i < cloud.size (); ++i)
{
- float normal[3];
+ float normal[3] = {0.0f, 0.0f, 0.0f};
normals->GetTupleValue (i, normal);
pcl::setFieldValue<PointT, float> (cloud[i], normal_x_idx, normal[0]);
pcl::setFieldValue<PointT, float> (cloud[i], normal_y_idx, normal[1]);
int length)
{
// The direction of the transfer is inferred from the requesttype field of the setup packet.
- unsigned char requesttype = (LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN);
+ const unsigned char requesttype = (static_cast<unsigned char>(LIBUSB_RECIPIENT_DEVICE) | static_cast<unsigned char>(LIBUSB_REQUEST_TYPE_VENDOR) | static_cast<unsigned char>(LIBUSB_ENDPOINT_IN));
// The value field for the setup packet
std::uint16_t value = 0x02;
// The index field for the setup packet
int length)
{
// The direction of the transfer is inferred from the requesttype field of the setup packet.
- unsigned char requesttype = (LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT);
+ const unsigned char requesttype = (static_cast<unsigned char>(LIBUSB_RECIPIENT_DEVICE) | static_cast<unsigned char>(LIBUSB_REQUEST_TYPE_VENDOR) | static_cast<unsigned char>(LIBUSB_ENDPOINT_OUT));
// The value field for the setup packet
std::uint16_t value = 0x01;
// The index field for the setup packet
Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero ();
getScatterMatrix (static_cast<int> (index), cov_m);
- Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m);
+ const Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m, Eigen::EigenvaluesOnly);
const double& e1c = solver.eigenvalues ()[2];
const double& e2c = solver.eigenvalues ()[1];
cloud_normals_.push_back (normals_);
cloud_trees_.push_back (tree_);
// Sort the clouds by their scales
- sort (scales_.begin (), scales_.end (), compareScalesFunction);
+ std::sort (scales_.begin (), scales_.end (), compareScalesFunction);
// Find the index of the input after sorting
for (std::size_t i = 0; i < scales_.size (); ++i)
char buf[BUFSIZ];
va_list ap;
va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
+ vsnprintf(buf, BUFSIZ, fmt, ap);
va_end(ap);
(*svm_print_string)(buf);
}
// octree not empty - we add another tree level and thus increase its size by a
// factor of 2*2*2
- child_idx = static_cast<unsigned char>(((bLowerBoundViolationX) << 2) |
- ((bLowerBoundViolationY) << 1) |
- ((bLowerBoundViolationZ)));
+ child_idx = static_cast<unsigned char>((bLowerBoundViolationX ? 4 : 0) |
+ (bLowerBoundViolationY ? 2 : 0) |
+ (bLowerBoundViolationZ ? 1 : 0));
BranchNode* newRootBranch;
else {
// we reached leaf node level
const auto* child_leaf = static_cast<const LeafNode*>(child_node);
- Indices decoded_point_vector;
-
- // decode leaf node into decoded_point_vector
- (*child_leaf)->getPointIndices(decoded_point_vector);
- // Linearly iterate over all decoded (unsorted) points
- for (const auto& index : decoded_point_vector) {
+ // Linearly iterate over all points in the leaf
+ for (const auto& index : (*child_leaf)->getPointIndicesVector()) {
const PointT& candidate_point = this->getPointByIndex(index);
// calculate point distance to search point
return leafDataTVector_;
}
+ /** \brief Retrieve const reference to point indices vector. This container stores a
+ * vector of point indices.
+ * \return const reference to vector of point indices to be stored within data vector
+ */
+ const pcl::Indices&
+ getPointIndicesVector() const
+ {
+ return leafDataTVector_;
+ }
+
/** \brief Get size of container (number of indices)
* \return number of point indices in container.
*/
set(SUBSYS_NAME outofcore)
set(SUBSYS_DESC "Point cloud outofcore library")
+if(BUILD_visualization)
set(SUBSYS_DEPS common io filters octree visualization)
+else()
+set(SUBSYS_DEPS common io filters octree)
+endif()
if(NOT TARGET Boost::filesystem)
set(DEFAULT FALSE)
set(LIB_NAME "pcl_${SUBSYS_NAME}")
-PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${visualization_incs})
-#PCL_ADD_SSE_FLAGS("${LIB_NAME}")
-target_link_libraries("${LIB_NAME}" pcl_common pcl_visualization ${Boost_SYSTEM_LIBRARY})
+if(BUILD_visualization)
+ PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${visualization_incs})
+ target_link_libraries("${LIB_NAME}" pcl_common pcl_visualization Boost::system Boost::filesystem)
+else()
+ PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs})
+ target_link_libraries("${LIB_NAME}" pcl_common Boost::system Boost::filesystem)
+endif()
if(HAVE_CJSON)
target_link_libraries("${LIB_NAME}" ${CJSON_LIBRARIES})
endif()
# Install include files
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}" ${incs})
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/impl" ${impl_incs})
-PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/visualization" ${visualization_incs})
+if(BUILD_visualization)
+ PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/visualization" ${visualization_incs})
+endif()
if(BUILD_tools)
add_subdirectory(tools)
#include <pcl/common/common.h>
#include <pcl/common/utils.h> // pcl::utils::ignore
+#ifdef PCL_VISUALIZATION_AVAILABLE
#include <pcl/visualization/common/common.h>
+#endif
#include <pcl/outofcore/octree_base_node.h>
#include <pcl/filters/random_sample.h>
#include <pcl/filters/extract_indices.h>
}
////////////////////////////////////////////////////////////////////////////////
-
+#ifdef PCL_VISUALIZATION_AVAILABLE
template<typename Container, typename PointT> void
OutofcoreOctreeBaseNode<Container, PointT>::queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list<std::string>& file_names, const std::uint32_t query_depth, const bool skip_vfc_check)
{
}
}
}
+#endif
////////////////////////////////////////////////////////////////////////////////
template<typename ContainerT, typename PointT> void
void
queryFrustum (const double planes[24], std::list<std::string>& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false);
+ /** \warning This function is only available if the visualization module is available and the preprocessor symbol `PCL_VISUALIZATION_AVAILABLE` is defined.
+ */
+#ifdef PCL_VISUALIZATION_AVAILABLE
void
queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list<std::string>& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false);
+#else
+ void
+ queryFrustum (const double planes[24], const Eigen::Vector3d &eye, const Eigen::Matrix4d &view_projection_matrix, std::list<std::string>& file_names, const std::uint32_t query_depth, const bool skip_vfc_check = false) = delete;
+#endif
//point extraction
/** \brief Recursively add points that fall into the queried bounding box up to the \b query_depth
camera_hud_actor_->GetTextProperty ()->SetColor (0.8, 0.8, 0.8);
camera_hud_actor_->GetTextProperty ()->SetJustificationToCentered ();
camera_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) / 2, 10);
- renderer_->AddActor2D (camera_hud_actor_);
+ renderer_->AddViewProp (camera_hud_actor_);
// HUD - FPS
fps_hud_actor_ = vtkSmartPointer<vtkTextActor>::New ();
fps_hud_actor_->GetTextProperty ()->SetJustificationToRight ();
fps_hud_actor_->SetInput ("fps");
fps_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) - 10, 10);
- renderer_->AddActor2D (fps_hud_actor_);
+ renderer_->AddViewProp (fps_hud_actor_);
// HUD - Points Loaded
points_hud_actor_ = vtkSmartPointer<vtkTextActor>::New ();
points_hud_actor_->GetTextProperty ()->SetJustificationToRight ();
points_hud_actor_->SetInput ("points/mb");
points_hud_actor_->SetPosition ((viewport_xmax - viewport_xmin) - 10, viewport_ymax - 20);
- renderer_->AddActor2D (points_hud_actor_);
+ renderer_->AddViewProp (points_hud_actor_);
// Callback - Viewport Modified - Window Resize
viewport_modified_callback_ = vtkSmartPointer<vtkCallbackCommand>::New ();
#cmakedefine HAVE_DAVIDSDK 1
+#ifndef PCL_HAS_NANOFLANN
+#cmakedefine PCL_HAS_NANOFLANN 1
+#endif
+
// SSE macros
#cmakedefine HAVE_POSIX_MEMALIGN
#cmakedefine HAVE_MM_MALLOC
#cmakedefine HAVE_QVTK 1
+#cmakedefine PCL_VISUALIZATION_AVAILABLE
{
Eigen::Transform<float, 3, Eigen::Affine> transform;
transform = transformation_;
- ground_coeffs_transformed_ = transform.matrix() * ground_coeffs_;
+ ground_coeffs_transformed_.noalias() = transform.matrix() * ground_coeffs_;
}
else
{
{
if (transformation_set_ && intrinsics_matrix_set_)
{
- intrinsics_matrix_transformed_ = intrinsics_matrix_ * transformation_.transpose();
+ intrinsics_matrix_transformed_.noalias() = intrinsics_matrix_ * transformation_.transpose();
}
else
{
"include/pcl/${SUBSYS_NAME}/impl/cg/geometric_consistency.hpp"
)
+# The cpp files have been ordered so that files with a long compile time appear at the top, to efficiently build in parallel. Do not reorder alphabetically!
set(srcs
+ src/cg/geometric_consistency.cpp
+ src/cg/hough_3d.cpp
src/linemod.cpp
src/quantizable_modality.cpp
src/dotmod.cpp
src/hv/hv_papazov.cpp
src/hv/hv_go.cpp
src/hv/greedy_verification.cpp
- src/cg/hough_3d.cpp
- src/cg/geometric_consistency.cpp
src/ransac_based/obj_rec_ransac.cpp
src/ransac_based/model_library.cpp
src/ransac_based/orr_octree.cpp
B, A, 0.0f,
0.0f, 0.0f, 1.0f;
- result = rotation_matrix_X * rotation_matrix_Z;
+ result.noalias() = rotation_matrix_X * rotation_matrix_Z;
return (result);
}
#endif
// Compute the bounds for the positional discretization
- float b[6]; scene_octree_.getBounds (b);
+ float b[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+ scene_octree_.getBounds (b);
float enlr = scene_bounds_enlargement_factor_*std::max (std::max (b[1]-b[0], b[3]-b[2]), b[5]-b[4]);
b[0] -= enlr; b[1] += enlr;
b[2] -= enlr; b[3] += enlr;
extern template class pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ>;
extern template class pcl::IterativeClosestPoint<pcl::PointXYZI, pcl::PointXYZI>;
extern template class pcl::IterativeClosestPoint<pcl::PointXYZRGB, pcl::PointXYZRGB>;
+extern template class pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointNormal>;
#endif // PCL_NO_PRECOMPILE
return;
}
- pcl::Indices inliers;
- sac.getInliers(inliers);
+ const auto& inliers = sac.getInliers();
if (inliers.size() < 3) {
remaining_correspondences = original_correspondences;
inlier_indices_.push_back(index_to_correspondence[inlier]);
}
- // get best transformation
- Eigen::VectorXf model_coefficients;
- sac.getModelCoefficients(model_coefficients);
+ // get the best transformation
+ const Eigen::VectorXf& model_coefficients = sac.getModelCoefficients();
best_transformation_.row(0) = model_coefficients.segment<4>(0);
best_transformation_.row(1) = model_coefficients.segment<4>(4);
best_transformation_.row(2) = model_coefficients.segment<4>(8);
"[pcl::registration::%s::getRemainingCorrespondences] Error refining model!\n",
getClassName().c_str());
- pcl::Indices inliers;
- sac.getInliers(inliers);
+ const auto& inliers = sac.getInliers();
if (inliers.size() < 3) {
PCL_ERROR("[pcl::registration::%s::getRemainingCorrespondences] Less than 3 "
remaining_correspondences[i] =
original_correspondences[index_to_correspondence[inliers[i]]];
- // get best transformation
- Eigen::VectorXf model_coefficients;
- sac.getModelCoefficients(model_coefficients);
+ // get the best transformation
+ const Eigen::VectorXf& model_coefficients = sac.getModelCoefficients();
best_transformation_.row(0) = model_coefficients.segment<4>(0);
best_transformation_.row(1) = model_coefficients.segment<4>(4);
best_transformation_.row(2) = model_coefficients.segment<4>(8);
double v = 1.; // biggest 2 singular values replaced by 1
if (k == 2) // smallest singular value replaced by gicp_epsilon
v = gicp_epsilon_;
- cov += v * col * col.transpose();
+ cov.noalias() += v * col * col.transpose();
}
cloud_covariances[i] = cov;
}
else
inverted_eigenvalues(i, i) = 1.0 / ev;
}
- delta = eigensolver.eigenvectors() * inverted_eigenvalues *
- eigensolver.eigenvectors().transpose() * gradient;
+ delta.noalias() = eigensolver.eigenvectors() * inverted_eigenvalues *
+ eigensolver.eigenvectors().transpose() * gradient;
// simple line search to guarantee a decrease in the function value
double alpha = 1.0;
// closes)
g.head<3>() += Md;
// Increment rotation gradient
- p_trans_src = gicp_->base_transformation_.template cast<float>() * p_src;
+ p_trans_src.noalias() = gicp_->base_transformation_.template cast<float>() * p_src;
Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]);
- dCost_dR_T += p_base_src * Md.transpose();
+ dCost_dR_T.noalias() += p_base_src * Md.transpose();
}
g.head<3>() *= 2.0 / m;
dCost_dR_T *= 2.0 / m;
// g.head<3> ()+= 2*M*d/num_matches (we postpone 2/num_matches after the loop
// closes)
g.head<3>() += Md;
- p_trans_src = gicp_->base_transformation_.template cast<float>() * p_src;
+ p_trans_src.noalias() = gicp_->base_transformation_.template cast<float>() * p_src;
Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]);
// Increment rotation gradient
- dCost_dR_T += p_base_src * Md.transpose();
+ dCost_dR_T.noalias() += p_base_src * Md.transpose();
}
f /= static_cast<double>(m);
g.head<3>() *= (2.0 / m);
const Eigen::Vector3d Md(M * d); // Md = M*d
gradient.head<3>() += Md; // translation gradient
hessian.topLeftCorner<3, 3>() += M; // translation-translation hessian
- p_trans_src = base_transformation_float * p_src;
+ p_trans_src.noalias() = base_transformation_float * p_src;
const Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]);
dCost_dR_T.noalias() += p_base_src * Md.transpose();
dCost_dR_T1b += p_base_src[0] * M;
base_transformation_ = Matrix4::Identity();
nr_iterations_ = 0;
converged_ = false;
- double dist_threshold = corr_dist_threshold_ * corr_dist_threshold_;
pcl::Indices nn_indices(1);
std::vector<float> nn_dists(1);
pcl::transformPointCloud(output, output, guess);
+ pcl::registration::CorrespondenceEstimation<PointSource, PointTarget, Scalar>
+ corr_estimation;
+ corr_estimation.setNumberOfThreads(threads_);
+ // setSearchMethodSource is not necessary because we do not use
+ // determineReciprocalCorrespondences
+ corr_estimation.setSearchMethodTarget(this->getSearchMethodTarget());
+ corr_estimation.setInputTarget(target_);
+ auto output_transformed = pcl::make_shared<PointCloudSource>();
+ output_transformed->resize(output.size());
+ pcl::Correspondences correspondences;
while (!converged_) {
std::size_t cnt = 0;
Eigen::Matrix3d R = transform_R.topLeftCorner<3, 3>();
- for (std::size_t i = 0; i < N; i++) {
- PointSource query = output[i];
- query.getVector4fMap() =
- transformation_.template cast<float>() * query.getVector4fMap();
-
- if (!searchForNeighbors(query, nn_indices, nn_dists)) {
- PCL_ERROR("[pcl::%s::computeTransformation] Unable to find a nearest neighbor "
- "in the target dataset for point %d in the source!\n",
- getClassName().c_str(),
- (*indices_)[i]);
- return;
- }
-
- // Check if the distance to the nearest neighbor is smaller than the user imposed
- // threshold
- if (nn_dists[0] < dist_threshold) {
- Eigen::Matrix3d& C1 = (*input_covariances_)[i];
- Eigen::Matrix3d& C2 = (*target_covariances_)[nn_indices[0]];
- Eigen::Matrix3d& M = mahalanobis_[i];
- // M = R*C1
- M = R * C1;
- // temp = M*R' + C2 = R*C1*R' + C2
- Eigen::Matrix3d temp = M * R.transpose();
- temp += C2;
- // M = temp^-1
- M = temp.inverse();
- source_indices[cnt] = static_cast<int>(i);
- target_indices[cnt] = nn_indices[0];
- cnt++;
- }
+ transformPointCloud(
+ output, *output_transformed, transformation_.template cast<float>(), false);
+ corr_estimation.setInputSource(output_transformed);
+ corr_estimation.determineCorrespondences(correspondences, corr_dist_threshold_);
+ cnt = 0;
+ for (const auto& corr : correspondences) {
+ source_indices[cnt] = corr.index_query;
+ target_indices[cnt] = corr.index_match;
+ const Eigen::Matrix3d& C1 = (*input_covariances_)[corr.index_query];
+ const Eigen::Matrix3d& C2 = (*target_covariances_)[corr.index_match];
+ pcl::invert3x3SymMatrix<Eigen::Matrix3d>(R * C1 * R.transpose() + C2,
+ mahalanobis_[corr.index_query]);
+ ++cnt;
}
// Resize to the actual number of valid correspondences
source_indices.resize(cnt);
PCL_DEBUG("[pcl::%s::computeTransformation] Convergence failed\n",
getClassName().c_str());
}
- final_transformation_ = previous_transformation_ * guess;
+ final_transformation_.noalias() = previous_transformation_ * guess;
PCL_DEBUG("Transformation "
"is:\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%"
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2]))
continue;
- pt_t = tr * pt;
+ pt_t.noalias() = tr * pt;
memcpy(data_out + x_idx_offset_, &pt_t[0], sizeof(float));
memcpy(data_out + y_idx_offset_, &pt_t[1], sizeof(float));
if (!std::isfinite(nt[0]) || !std::isfinite(nt[1]) || !std::isfinite(nt[2]))
continue;
- nt_t = rot * nt;
+ nt_t.noalias() = rot * nt;
memcpy(data_out + nx_idx_offset_, &nt_t[0], sizeof(float));
memcpy(data_out + ny_idx_offset_, &nt_t[1], sizeof(float));
if (!std::isfinite(pt[0]) || !std::isfinite(pt[1]) || !std::isfinite(pt[2]))
continue;
- pt_t = tr * pt;
+ pt_t.noalias() = tr * pt;
memcpy(data_out + x_idx_offset_, &pt_t[0], sizeof(float));
memcpy(data_out + y_idx_offset_, &pt_t[1], sizeof(float));
// 2009]
Eigen::JacobiSVD<Eigen::Matrix<double, 6, 6>> sv(
hessian, Eigen::ComputeFullU | Eigen::ComputeFullV);
+#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
+ if (sv.info() != Eigen::ComputationInfo::Success) {
+ trans_likelihood_ = score / static_cast<double>(input_->size());
+ converged_ = 0;
+ PCL_ERROR("[%s::computeTransformation] JacobiSVD on hessian failed!\n",
+ getClassName().c_str());
+ return;
+ }
+#endif
// Negative for maximization as opposed to minimization
Eigen::Matrix<double, 6, 1> delta = sv.solve(-score_gradient);
for (const auto& pt_index : pt_indices_) {
Eigen::Vector2d p(cloud[pt_index].x, cloud[pt_index].y);
sx += p;
- sxx += p * p.transpose();
+ sxx.noalias() += p * p.transpose();
}
n_ = pt_indices_.size();
Eigen::Matrix2d q = solver.eigenvectors();
// set minimum smallest eigenvalue:
l(0, 0) = l(1, 1) * min_covar_eigvalue_mult;
- covar = q * l * q.transpose();
+ covar.noalias() = q * l * q.transpose();
}
covar_inv_ = covar.inverse();
}
if (score.value != 0) {
// test for positive definiteness, and adjust to ensure it if necessary:
- Eigen::EigenSolver<Eigen::Matrix3d> solver;
- solver.compute(score.hessian, false);
+ Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver(score.hessian,
+ Eigen::EigenvaluesOnly);
double min_eigenvalue = 0;
for (int i = 0; i < 3; i++)
- if (solver.eigenvalues()[i].real() < min_eigenvalue)
- min_eigenvalue = solver.eigenvalues()[i].real();
+ if (solver.eigenvalues()[i] < min_eigenvalue)
+ min_eigenvalue = solver.eigenvalues()[i];
// ensure "safe" positive definiteness: this is a detail missing
// from the original paper
if (min_eigenvalue < 0) {
double lambda = 1.1 * min_eigenvalue - 1;
score.hessian += Eigen::Vector3d(-lambda, -lambda, -lambda).asDiagonal();
- solver.compute(score.hessian, false);
+ solver.compute(score.hessian, Eigen::EigenvaluesOnly);
PCL_DEBUG("[pcl::NormalDistributionsTransform2D::computeTransformation] adjust "
"hessian: %f: new eigenvalues:%f %f %f\n",
float(lambda),
- solver.eigenvalues()[0].real(),
- solver.eigenvalues()[1].real(),
- solver.eigenvalues()[2].real());
+ solver.eigenvalues()[0],
+ solver.eigenvalues()[1],
+ solver.eigenvalues()[2]);
}
- assert(solver.eigenvalues()[0].real() >= 0 &&
- solver.eigenvalues()[1].real() >= 0 &&
- solver.eigenvalues()[2].real() >= 0);
+ assert(solver.eigenvalues()[0] >= 0 && solver.eigenvalues()[1] >= 0 &&
+ solver.eigenvalues()[2] >= 0);
Eigen::Vector3d delta_transformation(-score.hessian.inverse() * score.grad);
Eigen::Vector3d new_transformation =
PCL_DEBUG("[PPFRegistration] Clustering poses (initially got %zu poses)\n",
poses.size());
// Start off by sorting the poses by the number of votes
- sort(poses.begin(), poses.end(), poseWithVotesCompareFunction);
+ std::sort(poses.begin(), poses.end(), poseWithVotesCompareFunction);
std::vector<PoseWithVotesList> clusters;
std::vector<std::pair<std::size_t, unsigned int>> cluster_votes;
if (!input_->is_dense && !pcl::isXYZFinite(point))
continue;
// Find its nearest neighbor in the target
- tree_->nearestKSearch(point, 1, nn_indices, nn_dists);
+ tree_->nearestKSearchT(point, 1, nn_indices, nn_dists);
// Deal with occlusions (incomplete targets)
if (nn_dists[0] <= max_range) {
deinitCompute();
}
-} // namespace pcl
\ No newline at end of file
+} // namespace pcl
transformation_matrix.template topLeftCorner<3, 3>() = R;
// transformation_matrix.block<3, 1>(0, 3) = source_mean.head<3>() - R *
// target_mean.head<3>();
- transformation_matrix.template block<3, 1>(0, 3) =
+ transformation_matrix.template block<3, 1>(0, 3).noalias() =
target_mean.template head<3>() - R * source_mean.template head<3>();
}
const Eigen::Matrix<double, 4, 4> A =
(0.25 / static_cast<double>(npts)) * C2.transpose() * C2 - C1;
- const Eigen::EigenSolver<Eigen::Matrix<double, 4, 4>> es(A);
+ const Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, 4, 4>> es(A);
ptrdiff_t i;
- es.eigenvalues().real().maxCoeff(&i);
- const Eigen::Matrix<double, 4, 1> qmat = es.eigenvectors().col(i).real();
+ es.eigenvalues().maxCoeff(&i);
+ const Eigen::Matrix<double, 4, 1> qmat = es.eigenvectors().col(i);
const Eigen::Matrix<double, 4, 1> smat =
-(0.5 / static_cast<double>(npts)) * C2 * qmat;
pcl::Indices& indices,
std::vector<float>& distances)
{
- int k = tree_->nearestKSearch(cloud, index, 1, indices, distances);
+ int k = tree_->nearestKSearchT(cloud[index], 1, indices, distances);
if (k == 0)
return (false);
return (true);
} // namespace pcl
#include <pcl/registration/impl/transformation_estimation_lm.hpp>
+
+#if !defined(PCL_NO_PRECOMPILE) && \
+ !defined(PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_CPP_)
+extern template class pcl::registration::TransformationEstimationLM<pcl::PointXYZ,
+ pcl::PointXYZ>;
+extern template class pcl::registration::TransformationEstimationLM<pcl::PointXYZI,
+ pcl::PointXYZI>;
+extern template class pcl::registration::TransformationEstimationLM<pcl::PointXYZRGB,
+ pcl::PointXYZRGB>;
+#endif // PCL_NO_PRECOMPILE
PCL_DEBUG("[pcl::%s::computeTransformation] Convergence failed\n",
getClassName().c_str());
}
- final_transformation_.topLeftCorner<3, 3>() =
+ final_transformation_.topLeftCorner<3, 3>().noalias() =
previous_transformation_.topLeftCorner<3, 3>() * guess.topLeftCorner<3, 3>();
final_transformation_(0, 3) = previous_transformation_(0, 3) + guess(0, 3);
final_transformation_(1, 3) = previous_transformation_(1, 3) + guess(1, 3);
template class PCL_EXPORTS pcl::IterativeClosestPoint<pcl::PointXYZI, pcl::PointXYZI>;
template class PCL_EXPORTS
pcl::IterativeClosestPoint<pcl::PointXYZRGB, pcl::PointXYZRGB>;
+template class PCL_EXPORTS pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointNormal>;
#endif // PCL_NO_PRECOMPILE
*
*/
+#define PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_LM_CPP_
#include <pcl/registration/transformation_estimation_lm.h>
+#include <pcl/pcl_config.h> // for PCL_NO_PRECOMPILE
+
+#ifndef PCL_NO_PRECOMPILE
+#include <pcl/pcl_exports.h> // for PCL_EXPORTS
+#include <pcl/point_types.h>
+template class PCL_EXPORTS
+ pcl::registration::TransformationEstimationLM<pcl::PointXYZ, pcl::PointXYZ>;
+template class PCL_EXPORTS
+ pcl::registration::TransformationEstimationLM<pcl::PointXYZI, pcl::PointXYZI>;
+template class PCL_EXPORTS
+ pcl::registration::TransformationEstimationLM<pcl::PointXYZRGB, pcl::PointXYZRGB>;
+#endif // PCL_NO_PRECOMPILE
return (0);
std::size_t nr_p = 0;
+ // C : Circle Center
+ const Eigen::Vector3d C (model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // N : Circle (Plane) Normal
+ const Eigen::Vector3d N (model_coefficients[4], model_coefficients[5], model_coefficients[6]);
+ // r : Radius
+ const double r = model_coefficients[3];
const auto squared_threshold = threshold * threshold;
// Iterate through the 3d points and calculate the distances from them to the sphere
for (std::size_t i = 0; i < indices_->size (); ++i)
// what i have:
// P : Sample Point
Eigen::Vector3d P ((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
- // C : Circle Center
- Eigen::Vector3d C (model_coefficients[0], model_coefficients[1], model_coefficients[2]);
- // N : Circle (Plane) Normal
- Eigen::Vector3d N (model_coefficients[4], model_coefficients[5], model_coefficients[6]);
- // r : Radius
- double r = model_coefficients[3];
Eigen::Vector3d helper_vectorPC = P - C;
// 1.1. get line parameter
Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>, double> lm (num_diff);
Eigen::VectorXd coeff = optimized_coefficients.cast<double>();
int info = lm.minimize (coeff);
- coeff.tail(3).normalize(); // normalize the cylinder axis
+ coeff.tail<3>().normalize(); // normalize the cylinder axis
for (Eigen::Index i = 0; i < coeff.size (); ++i)
optimized_coefficients[i] = static_cast<float> (coeff[i]);
#include <pcl/common/concatenate.h>
#include <Eigen/Eigenvalues>
-#include <complex>
//////////////////////////////////////////////////////////////////////////
const float con_F(neigvec(5));
// Build matrix M0
- const Eigen::MatrixXf M0 = (Eigen::MatrixXf(3, 3)
+ const Eigen::Matrix3f M0 = (Eigen::Matrix3f()
<< con_F, con_D/2.0, con_E/2.0,
con_D/2.0, con_A, con_B/2.0,
con_E/2.0, con_B/2.0, con_C)
.finished();
// Build matrix M
- const Eigen::MatrixXf M = (Eigen::MatrixXf(2, 2)
+ const Eigen::Matrix2f M = (Eigen::Matrix2f()
<< con_A, con_B/2.0,
con_B/2.0, con_C)
.finished();
// Calculate the eigenvalues and eigenvectors of matrix M
- Eigen::EigenSolver<Eigen::MatrixXf> solver_M(M);
+ const Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> solver_M(M, Eigen::EigenvaluesOnly);
- Eigen::VectorXf eigvals_M = solver_M.eigenvalues().real();
+ Eigen::Vector2f eigvals_M = solver_M.eigenvalues();
// Order the eigenvalues so that |lambda_0 - con_A| <= |lambda_0 - con_C|
float aux_eigval(0.0);
Eigen::Vector3f p_ctr;
float aux_par(0.0);
if (par_a > par_b) {
- p_ctr = p0 + Rot * Eigen::Vector3f(par_h, par_k, 0.0);
+ p_ctr.noalias() = p0 + Rot * Eigen::Vector3f(par_h, par_k, 0.0);
} else {
aux_par = par_a;
par_a = par_b;
par_b = aux_par;
- p_ctr = p0 + Rot * Eigen::Vector3f(par_k, par_h, 0.0);
+ p_ctr.noalias() = p0 + Rot * Eigen::Vector3f(par_k, par_h, 0.0);
}
// Center (x, y, z)
return;
}
- Eigen::Vector4f plane_parameters;
-
// Use Least-Squares to fit the plane through all the given sample points and find out its coefficients
EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
Eigen::Vector4f xyz_centroid;
B << -d.dot(p0), -d.dot(p1), -d.dot(p2), -d.dot(p3);
Eigen::Matrix<float, -1, -1> sol;
- sol = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B);
+ sol = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B);
const float r_min = -sol(0);
const float D = sol(1);
inliers.clear();
return;
}
+ const float squared_threshold = threshold * threshold;
inliers.clear();
error_sqr_dists_.clear();
inliers.reserve(indices_->size());
Eigen::Vector3f torus_closest;
projectPointToTorus(pt, pt_n, model_coefficients, torus_closest);
- const float distance = (torus_closest - pt).norm();
+ const float distance = (torus_closest - pt).squaredNorm();
- if (distance < threshold) {
+ if (distance < squared_threshold) {
// Returns the indices of the points whose distances are smaller than the
// threshold
inliers.push_back((*indices_)[i]);
- error_sqr_dists_.push_back(distance);
+ error_sqr_dists_.push_back(std::sqrt(distance));
}
}
}
if (!isModelValid(model_coefficients))
return (0);
+ const float squared_threshold = threshold * threshold;
std::size_t nr_p = 0;
for (std::size_t i = 0; i < indices_->size(); ++i) {
Eigen::Vector3f torus_closest;
projectPointToTorus(pt, pt_n, model_coefficients, torus_closest);
- const float distance = (torus_closest - pt).norm();
+ const float distance = (torus_closest - pt).squaredNorm();
- if (distance < threshold) {
+ if (distance < squared_threshold) {
nr_p++;
}
}
inline void
getModel (Indices &model) const { model = model_; }
- /** \brief Return the best set of inliers found so far for this model.
+ /**
+ * \brief Return the best model found so far.
+ * \return the resultant model
+ */
+ inline const Indices&
+ getModel() const {return model_; }
+
+ /** \brief Return the best set of inliers found so far for this model.
* \param[out] inliers the resultant set of inliers
*/
inline void
getInliers (Indices &inliers) const { inliers = inliers_; }
+ /** \brief Return the best set of inliers found so far for this model.
+ * \return the resultant set of inliers
+ */
+ inline const Indices&
+ getInliers() const {return inliers_; }
+
/** \brief Return the model coefficients of the best model found so far.
* \param[out] model_coefficients the resultant model coefficients, as documented in \ref sample_consensus
*/
inline void
getModelCoefficients (Eigen::VectorXf &model_coefficients) const { model_coefficients = model_coefficients_; }
+ /**
+ * \brief Return the model coefficients of the best model found so far.
+ * \return the resultant model coefficients
+ */
+ inline const Eigen::VectorXf&
+ getModelCoefficients() const {return model_coefficients_; }
+
protected:
/** \brief The underlying data model used (i.e. what is it that we attempt to search for). */
SampleConsensusModelPtr sac_model_;
set(incs
"include/pcl/${SUBSYS_NAME}/search.h"
"include/pcl/${SUBSYS_NAME}/kdtree.h"
+ "include/pcl/${SUBSYS_NAME}/kdtree_nanoflann.h"
"include/pcl/${SUBSYS_NAME}/brute_force.h"
"include/pcl/${SUBSYS_NAME}/organized.h"
"include/pcl/${SUBSYS_NAME}/octree.h"
std::size_t original_no_of_points = indices_ && !indices_->empty () ? indices_->size () : input_->size ();
if (input_copied_for_flann_)
- delete input_flann_->ptr();
+ delete[] input_flann_->ptr();
input_copied_for_flann_ = true;
index_mapping_.clear();
identity_mapping_ = true;
{
}
+template <typename PointT, class Tree>
+pcl::search::KdTree<PointT,Tree>::KdTree (const std::string& name, bool sorted)
+ : pcl::search::Search<PointT> (name, sorted)
+{
+}
+
///////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT, class Tree> void
pcl::search::KdTree<PointT,Tree>::setPointRepresentation (
const PointRepresentationConstPtr &point_representation)
{
- tree_->setPointRepresentation (point_representation);
+ if(tree_)
+ tree_->setPointRepresentation (point_representation);
+ else
+ PCL_ERROR("Calling setPointRepresentation on KdTreeNanoflann that has been cast to KdTree is not possible in this PCL version. Call setPointRepresentation directly on the KdTreeNanoflann object.\n");
}
///////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT, class Tree> void
pcl::search::KdTree<PointT,Tree>::setEpsilon (float eps)
{
- tree_->setEpsilon (eps);
+ if(tree_)
+ tree_->setEpsilon (eps);
+ else
+ PCL_ERROR("Calling setEpsilon on KdTreeNanoflann that has been cast to KdTree is not possible in this PCL version. Call setEpsilon directly on the KdTreeNanoflann object.\n");
}
///////////////////////////////////////////////////////////////////////////////////////////
KR_ = projection_matrix_.topLeftCorner <3, 3> ();
// precalculate KR * KR^T needed by calculations during nn-search
- KR_KRT_ = KR_ * KR_.transpose ();
+ KR_KRT_.noalias() = KR_ * KR_.transpose ();
+ return true;
+}
- // final test: project a few points at known image coordinates and test if the projected coordinates are close
+template<typename PointT> bool
+pcl::search::OrganizedNeighbor<PointT>::testProjectionMatrix () const
+{
+ // test: project a few points at known image coordinates and test if the projected coordinates are close
for(std::size_t i=0; i<11; ++i) {
const std::size_t test_index = input_->size()*i/11u;
if (!mask_[test_index])
const auto& test_point = (*input_)[test_index];
pcl::PointXY q;
if (!projectPoint(test_point, q) || std::abs(q.x-test_index%input_->width)>1 || std::abs(q.y-test_index/input_->width)>1) {
- PCL_WARN ("[pcl::%s::estimateProjectionMatrix] Input dataset does not seem to be from a projective device! (point %zu (%g,%g,%g) projected to pixel coordinates (%g,%g), but actual pixel coordinates are (%zu,%zu))\n",
+ PCL_WARN ("[pcl::%s::testProjectionMatrix] Input dataset does not seem to be from a projective device! (point %zu (%g,%g,%g) projected to pixel coordinates (%g,%g), but actual pixel coordinates are (%zu,%zu))\n",
this->getName ().c_str (), test_index, test_point.x, test_point.y, test_point.z, q.x, q.y, static_cast<std::size_t>(test_index%input_->width), static_cast<std::size_t>(test_index/input_->width));
return false;
}
order [idx] = static_cast<index_t> (idx);
Compare compare (distances);
- sort (order.begin (), order.end (), compare);
+ std::sort (order.begin (), order.end (), compare);
Indices sorted (indices.size ());
for (std::size_t idx = 0; idx < order.size (); ++idx)
indices = sorted;
// sort the according distances.
- sort (distances.begin (), distances.end ());
+ std::sort (distances.begin (), distances.end ());
}
#define PCL_INSTANTIATE_Search(T) template class PCL_EXPORTS pcl::search::Search<T>;
std::vector<float> &k_sqr_distances,
unsigned int max_nn = 0) const override;
protected:
+ /** \brief This leaves the internal tree_ object uninitialized! */
+ KdTree (const std::string& name, bool sorted);
/** \brief A pointer to the internal KdTree object. */
KdTreePtr tree_;
};
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2025-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#pragma once
+
+#include <pcl/pcl_config.h>
+#if PCL_HAS_NANOFLANN || defined(DOXYGEN_ONLY)
+
+#include <pcl/search/kdtree.h>
+#include <pcl/point_representation.h>
+
+#include <nanoflann.hpp>
+
+namespace pcl {
+namespace search {
+namespace internal {
+/** Helper for KdTreeNanoflann, serves as a dataset adaptor.
+ */
+template <typename T = float>
+struct PointCloudAdaptor {
+ PointCloudAdaptor(const T* data,
+ bool delete_data,
+ std::size_t dim,
+ std::size_t point_count)
+ : data_(data), delete_data_(delete_data), dim_(dim), point_count_(point_count)
+ {}
+
+ ~PointCloudAdaptor()
+ {
+ if (delete_data_)
+ delete[] data_;
+ }
+
+ inline void
+ reset_adaptor(const T* data,
+ bool delete_data,
+ std::size_t dim,
+ std::size_t point_count)
+ {
+ if (delete_data_)
+ delete[] data_;
+ data_ = data;
+ delete_data_ = delete_data;
+ dim_ = dim;
+ point_count_ = point_count;
+ }
+
+ inline std::size_t
+ kdtree_get_point_count() const
+ {
+ return point_count_;
+ }
+
+ inline T
+ kdtree_get_pt(const std::size_t idx, const std::size_t dim) const
+ {
+ return data_[dim_ * idx + dim];
+ }
+
+ template <class BBOX>
+ bool
+ kdtree_get_bbox(BBOX& /* bb */) const
+ {
+ return false;
+ }
+
+private:
+ const T* data_;
+ bool delete_data_;
+ std::size_t dim_;
+ std::size_t point_count_;
+};
+
+/** Helper function for radiusSearch: must have a template specialization if the
+ * distance norm is L2
+ */
+template <typename Dist>
+float
+square_if_l2(float radius)
+{
+ return radius;
+};
+template <>
+float
+square_if_l2<nanoflann::L2_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>>(float radius)
+{
+ return radius * radius;
+};
+template <>
+float
+square_if_l2<
+ nanoflann::L2_Simple_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>>(float radius)
+{
+ return radius * radius;
+};
+} // namespace internal
+
+// for convenience/brevity
+using L1_Adaptor =
+ nanoflann::L1_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>;
+using L2_Adaptor =
+ nanoflann::L2_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>;
+using L2_Simple_Adaptor =
+ nanoflann::L2_Simple_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>;
+using SO2_Adaptor =
+ nanoflann::SO2_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>;
+using SO3_Adaptor =
+ nanoflann::SO3_Adaptor<float,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ float,
+ pcl::index_t>;
+// TODO maybe additional adaptor with simd?
+
+/** @brief @b pcl::search::KdTreeNanoflann is a faster and flexible alternative to
+ * pcl::search::KdTree. It is based on the nanoflann library by Jose Luis Blanco-Claraco
+ * ( https://github.com/jlblancoc/nanoflann ). Since nanoflann is treated as an optional
+ * dependency to PCL, you must test the preprocessor symbol `PCL_HAS_NANOFLANN` after
+ * including `pcl/search/kdtree_nanoflann.h`.
+ * @code
+ * // Example 1: using KdTreeNanoflann in NormalEstimation:
+ * pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
+ * auto tree = pcl::make_shared<pcl::search::KdTreeNanoflann<pcl::PointXYZ>>();
+ * ne.setSearchMethod (tree);
+ * // rest as usual
+ * // Example 2: using KdTreeNanoflannn in ICP:
+ * pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
+ * icp.setSearchMethodSource(pcl::make_shared<pcl::search::KdTreeNanoflann<pcl::PointXYZ>>());
+ * icp.setSearchMethodTarget(pcl::make_shared<pcl::search::KdTreeNanoflann<pcl::PointXYZ>>());
+ * // rest as usual
+ * // Example 3: using a L1 distance norm:
+ * pcl::search::KdTreeNanoflann<PointXYZ, 3, pcl::search::L1_Adaptor> kdtree_nanoflann;
+ * kdtree_nanoflann.setInputCloud (my_cloud);
+ * // now ready to use kdtree_nanoflann.nearestKSearch(...) and
+ * // kdtree_nanoflann.radiusSearch(...);
+ * // Example 4: using KdTreeNanoflann with features instead of 3D points:
+ * pcl::search::KdTreeNanoflann<pcl::FPFHSignature33, 33> kdtree_nanoflann_feat;
+ * kdtree_nanoflann_feat.setInputCloud(my_features_cloud);
+ * // now ready for searching
+ * @endcode
+ *
+ * @tparam PointT Can be a point like pcl::PointXYZ or a feature like pcl::SHOT352
+ * @tparam Dim Dimension of the KdTree to build. If set to -1, it will infer the
+ * dimension at runtime from the given point representation, but with a performance
+ * penalty. Default is 3, appropriate for all xyz point types.
+ * @tparam Distance The distance to use. Possible values include pcl::L1_Adaptor
+ * (taxicab/manhattan distance), pcl::L2_Simple_Adaptor (euclidean distance, optimized
+ * for few dimensions), pcl::L2_Adaptor (euclidean distance, optimized for many
+ * dimensions), pcl::SO2_Adaptor, pcl::SO3_Adaptor. Default is pcl::L2_Simple_Adaptor
+ *
+ * @author Markus Vieth
+ * @ingroup search
+ */
+template <typename PointT,
+ std::int32_t Dim = 3,
+ typename Distance =
+ std::conditional_t<Dim >= 4, L2_Adaptor, L2_Simple_Adaptor>,
+ typename Tree = nanoflann::KDTreeSingleIndexAdaptor<
+ Distance,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ Dim,
+ pcl::index_t>>
+class KdTreeNanoflann : public pcl::search::KdTree<PointT> {
+private:
+ /** The special thing here is that indices and distances are stored in _two_ vectors,
+ * not as a pair in _one_ vector.
+ */
+ template <typename _DistanceType = float, typename _IndexType = pcl::index_t>
+ class PCLRadiusResultSet {
+ public:
+ using DistanceType = _DistanceType;
+ using IndexType = _IndexType;
+
+ public:
+ const DistanceType radius;
+
+ std::vector<IndexType>& m_indices;
+ std::vector<DistanceType>& m_dists;
+ std::size_t max_results_;
+
+ explicit PCLRadiusResultSet(
+ DistanceType radius_,
+ std::vector<IndexType>& indices,
+ std::vector<DistanceType>& dists,
+ std::size_t max_results = std::numeric_limits<std::size_t>::max())
+ : radius(radius_), m_indices(indices), m_dists(dists), max_results_(max_results)
+ {
+ init();
+ }
+
+ void
+ init()
+ {
+ clear();
+ if (max_results_ != std::numeric_limits<std::size_t>::max()) {
+ m_indices.reserve(max_results_);
+ m_dists.reserve(max_results_);
+ }
+ }
+ void
+ clear()
+ {
+ m_indices.clear();
+ m_dists.clear();
+ }
+
+ size_t
+ size() const
+ {
+ return m_indices.size();
+ }
+ size_t
+ empty() const
+ {
+ return m_indices.empty();
+ }
+
+ bool
+ full() const
+ {
+ return true;
+ }
+
+ /**
+ * Called during search to add an element matching the criteria.
+ * @return true if the search should be continued, false if the results are
+ * sufficient
+ */
+ bool
+ addPoint(DistanceType dist, IndexType index)
+ {
+ if (dist < radius) {
+ m_indices.emplace_back(index);
+ m_dists.emplace_back(dist);
+ }
+ return (m_indices.size() < max_results_);
+ }
+
+ DistanceType
+ worstDist() const
+ {
+ return radius;
+ }
+
+ void
+ sort()
+ {
+ // this sort function does not do anything (yet). For now, PCLRadiusResultSet
+ // should only be used if the results do not have to be sorted. In the future, we
+ // might add sorting here if we find a really efficient way to sort both vectors
+ // simultaneously.
+ }
+ };
+
+public:
+ using PointCloud = typename Search<PointT>::PointCloud;
+ using PointCloudConstPtr = typename pcl::PointCloud<PointT>::ConstPtr;
+
+ using pcl::search::Search<PointT>::indices_;
+ using pcl::search::Search<PointT>::input_;
+ using pcl::search::Search<PointT>::getIndices;
+ using pcl::search::Search<PointT>::getInputCloud;
+ using pcl::search::Search<PointT>::nearestKSearch;
+ using pcl::search::Search<PointT>::radiusSearch;
+ using pcl::search::Search<PointT>::sorted_results_;
+ using pcl::search::Search<PointT>::name_;
+
+ using Ptr = shared_ptr<KdTreeNanoflann<PointT, Dim, Distance, Tree>>;
+ using ConstPtr = shared_ptr<const KdTreeNanoflann<PointT, Dim, Distance, Tree>>;
+
+ using KdTreePtr = shared_ptr<Tree>;
+ using KdTreeConstPtr = shared_ptr<const Tree>;
+ using PointRepresentationConstPtr = shared_ptr<const PointRepresentation<PointT>>;
+
+ /** @brief Constructor for KdTreeNanoflann.
+ *
+ * @param[in] sorted Set to true if the nearest neighbor search results
+ * need to be sorted in ascending order based on their distance to the
+ * query point (default is false, which is faster)
+ * @param[in] leaf_max_size Max number of points/samples in a leaf, can be tuned to
+ * achieve best performance. When using this for 1nn search (e.g. correspondence
+ * estimation in icp/registration), then leaf_max_size=10 is usually fastest.
+ * Otherwise, leaf_max_size=20 is a good choice.
+ * @param[in] n_thread_build Number of threads for concurrent tree build (default is
+ * 1, meaning no concurrent build)
+ */
+ KdTreeNanoflann(bool sorted,
+ std::size_t leaf_max_size,
+ unsigned int n_thread_build = 1)
+ : pcl::search::KdTree<PointT>("KdTreeNanoflann", sorted)
+ , leaf_max_size_(leaf_max_size)
+ , n_thread_build_(n_thread_build)
+ {}
+
+ /** @brief Constructor for KdTreeNanoflann.
+ *
+ * @param[in] sorted set to true if the nearest neighbor search results
+ * need to be sorted in ascending order based on their distance to the
+ * query point
+ *
+ */
+ KdTreeNanoflann(bool sorted = false) : KdTreeNanoflann(sorted, 15, 1) {}
+
+ /** @brief Destructor for KdTreeNanoflann. */
+ ~KdTreeNanoflann() override = default;
+
+ /** @brief Provide a pointer to the point representation to use to convert points into
+ * k-D vectors. If you want to use this function, it is recommended to do so _before_
+ * calling setInputCloud, to avoid setting up the kd-tree twice.
+ * @param[in] point_representation the const shared pointer to a PointRepresentation
+ */
+ void
+ setPointRepresentation(const PointRepresentationConstPtr& point_representation)
+ {
+ PCL_DEBUG("[KdTreeNanoflann::setPointRepresentation] "
+ "KdTreeNanoflann::setPointRepresentation called, "
+ "point_representation->getNumberOfDimensions()=%i, "
+ "point_representation->isTrivial()=%i\n",
+ point_representation->getNumberOfDimensions(),
+ point_representation->isTrivial());
+ if (Dim != -1 && Dim != point_representation->getNumberOfDimensions()) {
+ PCL_ERROR("[KdTreeNanoflann::setPointRepresentation] The given point "
+ "representation uses %i dimensions, but the nr of dimensions given as "
+ "template parameter to KdTreeNanoflann is %i.\n",
+ point_representation->getNumberOfDimensions(),
+ Dim);
+ return;
+ }
+ point_representation_ = point_representation;
+ setUpTree();
+ }
+
+ /** @brief Get a pointer to the point representation used when converting points into
+ * k-D vectors. */
+ inline PointRepresentationConstPtr
+ getPointRepresentation() const
+ {
+ return point_representation_;
+ }
+
+ /** @brief Sets whether the results have to be sorted or not.
+ * @param[in] sorted_results set to true if the radius search results should be sorted
+ */
+ void
+ setSortedResults(bool sorted_results) override
+ {
+ sorted_results_ = sorted_results;
+ }
+
+ /** @brief Set the search epsilon precision (error bound) for nearest neighbors
+ * searches.
+ * @param[in] eps precision (error bound) for nearest neighbors searches
+ */
+ void
+ setEpsilon(float eps)
+ {
+ eps_ = eps;
+ }
+
+ /** @brief Get the search epsilon precision (error bound) for nearest neighbors
+ * searches. */
+ inline float
+ getEpsilon() const
+ {
+ return eps_;
+ }
+
+ /** @brief Influences the results of radiusSearch when max_nn is not set to zero.
+ * If the parameter max_nn of radiusSearch is set to a value greater than zero, it
+ * will return _at most_ that many points. If you set `use_rknn=true`, it will always
+ * return the points _closest_ to the query point. If you set `use_rknn=false`, it may
+ * return _any_ points within the radius, which can be faster.
+ */
+ void
+ setUseRKNN(bool use_rknn)
+ {
+ use_rknn_ = use_rknn;
+ }
+
+ /** @brief Provide a pointer to the input dataset, this will build the kd-tree.
+ * @param[in] cloud the const shared pointer to a PointCloud
+ * @param[in] indices the point indices subset that is to be used from \a cloud
+ */
+ bool
+ setInputCloud(const PointCloudConstPtr& cloud,
+ const IndicesConstPtr& indices = IndicesConstPtr()) override
+ {
+ input_ = cloud;
+ indices_ = indices;
+
+ return setUpTree();
+ }
+
+ /** @brief Get pointer to internal nanoflann tree. Use with caution.
+ */
+ KdTreePtr
+ getNanoflannTree()
+ {
+ return nanoflann_tree_;
+ }
+
+ /** @brief Search for the k-nearest neighbors for the given query point.
+ * @param[in] point the given query point
+ * @param[in] k the number of neighbors to search for
+ * @param[out] k_indices the resultant indices of the neighboring points (must be
+ * resized to \a k a priori!)
+ * @param[out] k_sqr_distances the resultant squared distances to the neighboring
+ * points (must be resized to \a k a priori!)
+ * @return number of neighbors found
+ */
+ int
+ nearestKSearch(const PointT& point,
+ int k,
+ Indices& k_indices,
+ std::vector<float>& k_sqr_distances) const override
+ {
+ assert(point_representation_->isValid(point) &&
+ "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
+ if (static_cast<std::size_t>(k) > adaptor_->kdtree_get_point_count())
+ k = adaptor_->kdtree_get_point_count();
+ k_indices.resize(k);
+ k_sqr_distances.resize(k);
+ float* query_point = nullptr;
+ if (!point_representation_->isTrivial()) {
+ query_point = new float[point_representation_->getNumberOfDimensions()];
+ point_representation_->vectorize(point, query_point);
+ }
+ // like nanoflann_tree_->knnSearch
+ nanoflann::KNNResultSet<float, pcl::index_t> resultSet(k);
+ resultSet.init(k_indices.data(), k_sqr_distances.data());
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point))
+#if NANOFLANN_VERSION < 0x150
+ ,
+ nanoflann::SearchParams()
+#endif // NANOFLANN_VERSION < 0x150
+ );
+ const auto search_result = resultSet.size();
+ delete[] query_point;
+ assert(search_result == k);
+
+ if (!identity_mapping_) {
+ for (auto& index : k_indices) {
+ index = index_mapping_[index];
+ }
+ }
+ return search_result;
+ }
+
+ /** @brief Search for all the nearest neighbors of the query point in a given radius.
+ * @param[in] point the given query point
+ * @param[in] radius the radius of the sphere bounding all of p_q's neighbors
+ * @param[out] k_indices the resultant indices of the neighboring points
+ * @param[out] k_sqr_distances the resultant squared distances to the neighboring
+ * points
+ * @param[in] max_nn if given, bounds the maximum returned neighbors to this value. If
+ * \a max_nn is set to 0 or to a number higher than the number of points in the input
+ * cloud, all neighbors in \a radius will be returned.
+ * @return number of neighbors found in radius
+ */
+ int
+ radiusSearch(const PointT& point,
+ double radius,
+ Indices& k_indices,
+ std::vector<float>& k_sqr_distances,
+ unsigned int max_nn = 0) const override
+ {
+ assert(point_representation_->isValid(point) &&
+ "Invalid (NaN, Inf) point coordinates given to radiusSearch!");
+ float* query_point = nullptr;
+ if (!point_representation_->isTrivial()) {
+ query_point = new float[point_representation_->getNumberOfDimensions()];
+ point_representation_->vectorize(point, query_point);
+ }
+ if (max_nn == 0) {
+ // return _all_ points within radius
+ // Calling this->sortResults is currently slower than sorting the vector of
+ // nanoflann::ResultItem However, if sorted results are not requested, using
+ // PCLRadiusResultSet with radiusSearchCustomCallback avoids copies and is faster
+ if (sorted_results_) {
+#if NANOFLANN_VERSION < 0x150
+ std::vector<std::pair<pcl::index_t, float>>
+ IndicesDists; // nanoflann::ResultItem was introduced in version 1.5.0
+#else
+ std::vector<nanoflann::ResultItem<pcl::index_t, float>> IndicesDists;
+#endif // NANOFLANN_VERSION < 0x150
+ // like nanoflann_tree_->radiusSearch
+ nanoflann::RadiusResultSet<float, pcl::index_t> resultSet(
+ pcl::search::internal::square_if_l2<Distance>(radius), IndicesDists);
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point)),
+#if NANOFLANN_VERSION < 0x150
+ {32, eps_, sorted_results_} // first parameter is ignored in older versions,
+ // and removed in newer versions
+#else
+ {eps_, sorted_results_}
+#endif // NANOFLANN_VERSION < 0x150
+ );
+#if NANOFLANN_VERSION < 0x160
+ // before, nanoflann did not sort in findNeighbours
+ if (sorted_results_)
+ std::sort(
+ IndicesDists.begin(), IndicesDists.end(), nanoflann::IndexDist_Sorter());
+#endif // NANOFLANN_VERSION < 0x160
+ const auto search_result = resultSet.size();
+ k_indices.resize(IndicesDists.size());
+ k_sqr_distances.resize(IndicesDists.size());
+ for (std::size_t i = 0; i < IndicesDists.size(); ++i) {
+ k_indices[i] = identity_mapping_ ? IndicesDists[i].first
+ : index_mapping_[IndicesDists[i].first];
+ k_sqr_distances[i] = IndicesDists[i].second;
+ }
+ delete[] query_point;
+ return search_result;
+ }
+ else {
+ PCLRadiusResultSet<float, pcl::index_t> resultSet(
+ pcl::search::internal::square_if_l2<Distance>(radius),
+ k_indices,
+ k_sqr_distances);
+ // like nanoflann_tree_->radiusSearchCustomCallback
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point)),
+#if NANOFLANN_VERSION < 0x150
+ {32, eps_, sorted_results_} // first parameter is ignored in older versions,
+ // and removed in newer versions
+#else
+ {eps_, sorted_results_}
+#endif // NANOFLANN_VERSION < 0x150
+ );
+ const auto search_result = resultSet.size();
+ if (!identity_mapping_) {
+ for (auto& index : k_indices) {
+ index = index_mapping_[index];
+ }
+ }
+ if (sorted_results_)
+ this->sortResults(k_indices, k_sqr_distances);
+ delete[] query_point;
+ return search_result;
+ }
+ }
+ else {
+ // return no more than max_nn points
+ if (use_rknn_) {
+ // return points closest to query point
+ if (static_cast<std::size_t>(max_nn) > adaptor_->kdtree_get_point_count())
+ max_nn = adaptor_->kdtree_get_point_count();
+ k_indices.resize(max_nn);
+ k_sqr_distances.resize(max_nn);
+#if NANOFLANN_VERSION < 0x151
+ // rknnSearch and RKNNResultSet were added in nanoflann 1.5.1, so do knn search
+ // and discard those neighbors that are outside of search radius
+ nanoflann::KNNResultSet<float, pcl::index_t> resultSet(max_nn);
+ resultSet.init(k_indices.data(), k_sqr_distances.data());
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point))
+#if NANOFLANN_VERSION < 0x150
+ ,
+ nanoflann::SearchParams()
+#endif // NANOFLANN_VERSION < 0x150
+ );
+ auto search_result = resultSet.size();
+ for (auto iter = k_sqr_distances.rbegin();
+ iter != k_sqr_distances.rend() &&
+ *iter > pcl::search::internal::square_if_l2<Distance>(radius);
+ ++iter) {
+ --search_result;
+ }
+ k_indices.resize(search_result);
+ k_sqr_distances.resize(search_result);
+#else
+ // like nanoflann_tree_->rknnSearch
+ nanoflann::RKNNResultSet<float, pcl::index_t> resultSet(
+ max_nn, pcl::search::internal::square_if_l2<Distance>(radius));
+ resultSet.init(k_indices.data(), k_sqr_distances.data());
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point)));
+ const auto search_result = resultSet.size();
+ k_indices.resize(search_result);
+ k_sqr_distances.resize(search_result);
+#endif // NANOFLANN_VERSION < 0x151
+ if (!identity_mapping_) {
+ for (auto& index : k_indices) {
+ index = index_mapping_[index];
+ }
+ }
+ delete[] query_point;
+ return search_result;
+ }
+ else {
+ // may return any points within the radius, can be faster
+ PCLRadiusResultSet<float, pcl::index_t> resultSet(
+ pcl::search::internal::square_if_l2<Distance>(radius),
+ k_indices,
+ k_sqr_distances,
+ max_nn);
+ // like nanoflann_tree_->radiusSearchCustomCallback
+ nanoflann_tree_->findNeighbors(
+ resultSet,
+ (query_point ? query_point : reinterpret_cast<const float*>(&point)),
+#if NANOFLANN_VERSION < 0x150
+ {32, eps_, sorted_results_} // first parameter is ignored in older versions,
+ // and removed in newer versions
+#else
+ {eps_, sorted_results_}
+#endif // NANOFLANN_VERSION < 0x150
+ );
+ const auto search_result = resultSet.size();
+ if (!identity_mapping_) {
+ for (auto& index : k_indices) {
+ index = index_mapping_[index];
+ }
+ }
+ if (sorted_results_)
+ this->sortResults(k_indices, k_sqr_distances);
+ delete[] query_point;
+ return search_result;
+ }
+ }
+ }
+
+private:
+ /** Set up index_mapping_, adaptor_, and nanoflann_tree_, based on
+ * point_representation_, input_, and indices_.
+ */
+ bool
+ setUpTree()
+ {
+ if (!point_representation_ || !input_ || input_->empty()) {
+ PCL_ERROR("[KdTreeNanoflann::setUpTree] point representation is null or input is "
+ "null or input is empty\n");
+ return false;
+ }
+
+ const std::size_t dim = point_representation_->getNumberOfDimensions();
+ if (Dim != -1 && Dim != static_cast<int>(dim)) {
+ PCL_ERROR("[KdTreeNanoflann::setUpTree] The given point "
+ "representation uses %i dimensions, but the nr of dimensions given as "
+ "template parameter to KdTreeNanoflann is %i.\n",
+ dim,
+ Dim);
+ return false;
+ }
+ index_mapping_.clear();
+ if (indices_ && !indices_->empty()) {
+ index_mapping_.reserve(indices_->size());
+ for (const auto& index : *indices_) {
+ if (point_representation_->isValid((*input_)[index])) {
+ index_mapping_.emplace_back(index);
+ }
+ }
+ }
+ else {
+ index_mapping_.reserve(input_->size());
+ for (std::size_t index = 0; index < input_->size(); ++index) {
+ if (point_representation_->isValid((*input_)[index])) {
+ index_mapping_.emplace_back(index);
+ }
+ }
+ }
+ identity_mapping_ = true;
+ for (pcl::index_t index = 0;
+ identity_mapping_ && static_cast<std::size_t>(index) < index_mapping_.size();
+ ++index) {
+ identity_mapping_ = identity_mapping_ && index_mapping_[index] == index;
+ }
+
+ PCL_DEBUG("[KdTreeNanoflann::setUpTree] identity_mapping_=%i, "
+ "point_representation_->getNumberOfDimensions()=%lu, "
+ "point_representation_->isTrivial ()=%i\n",
+ identity_mapping_ ? 1 : 0,
+ dim,
+ point_representation_->isTrivial() ? 1 : 0);
+ if (identity_mapping_ && point_representation_->isTrivial() &&
+ sizeof(PointT) % sizeof(float) == 0) {
+ // no need to allocate memory and copy data
+ PCL_DEBUG("[KdTreeNanoflann::setUpTree] Mapping cloud directly, without "
+ "allocating memory.\n");
+ adaptor_.reset(new internal::PointCloudAdaptor<float>(
+ reinterpret_cast<const float*>(&(*input_)[0]),
+ false,
+ sizeof(PointT) / sizeof(float),
+ index_mapping_.size()));
+ }
+ else {
+ float* data = new float[dim * index_mapping_.size()];
+ float* data_itr = data;
+ for (auto& index : index_mapping_) {
+ point_representation_->vectorize((*input_)[index], data_itr);
+ data_itr += dim;
+ }
+ adaptor_.reset(new internal::PointCloudAdaptor<float>(
+ data, true, dim, index_mapping_.size()));
+ }
+ nanoflann_tree_.reset(
+ new Tree(dim,
+ *adaptor_,
+#if NANOFLANN_VERSION >= 0x150
+ // concurrent tree building is possible since nanoflann 1.5.0
+ {leaf_max_size_,
+ nanoflann::KDTreeSingleIndexAdaptorFlags::None,
+ n_thread_build_}));
+#else
+ {leaf_max_size_}));
+ if (n_thread_build_ != 1)
+ PCL_WARN("[KdTreeNanoflann::setUpTree] concurrent tree building is only possible "
+ "with nanoflann version 1.5.0 and newer\n");
+#endif // NANOFLANN_VERSION >= 0x150
+ return true;
+ }
+
+ KdTreePtr nanoflann_tree_;
+
+ shared_ptr<internal::PointCloudAdaptor<float>> adaptor_;
+
+ PointRepresentationConstPtr point_representation_{
+ new DefaultPointRepresentation<PointT>};
+
+ Indices index_mapping_;
+
+ bool identity_mapping_{false};
+
+ std::size_t leaf_max_size_{15};
+
+ unsigned int n_thread_build_{1};
+
+ float eps_{0.0f};
+
+ bool use_rknn_{true};
+};
+} // namespace search
+} // namespace pcl
+#ifdef PCL_NO_PRECOMPILE
+#include <pcl/search/impl/kdtree.hpp>
+#endif
+
+#else
+//#warning "KdTreeNanoflann is not available"
+#endif // PCL_HAS_NANOFLANN
mask_[idx] = 1;
}
- return estimateProjectionMatrix () && isValid ();
+ return (eps_ < 0 || estimateProjectionMatrix ()) && testProjectionMatrix() && isValid ();
}
/** \brief Search for all neighbors of query point that are within a given radius.
std::vector<float> &k_sqr_distances,
unsigned int max_nn = 0) const override;
- /** \brief estimated the projection matrix from the input cloud. */
+ /** \brief Estimate the projection matrix from the input cloud.
+ * \return True if it was possible to estimate the matrix, false otherwise
+ */
bool
estimateProjectionMatrix ();
+ /** \brief Quick test if projection matrix and input cloud work together.
+ */
+ bool
+ testProjectionMatrix () const;
+
+ /** \brief Set projection matrix manually. Projection matrix will _not_ be estimated automatically any more. If you want to use this, call it _before_ setInputCloud.
+ */
+ void
+ setProjectionMatrix (const Eigen::Matrix<float, 3, 4>& projection_matrix)
+ {
+ eps_ = -1.0f; // signal to not call estimateProjectionMatrix
+ projection_matrix_ = projection_matrix;
+ // rest is the same as in estimateProjectionMatrix():
+ // get left 3x3 sub matrix, which contains K * R, with K = camera matrix = [[fx s cx] [0 fy cy] [0 0 1]]
+ // and R being the rotation matrix
+ KR_ = projection_matrix_.topLeftCorner <3, 3> ();
+
+ // precalculate KR * KR^T needed by calculations during nn-search
+ KR_KRT_ = KR_ * KR_.transpose ();
+ }
+
/** \brief Search for the k-nearest neighbors for a given query point.
* \note limiting the maximum search radius (with setMaxDistance) can lead to a significant improvement in search speed
* \param[in] p_q the given query point (\ref setInputCloud must be given a-priori!)
Eigen::Matrix<float, 3, 3, Eigen::RowMajor> KR_KRT_;
/** \brief epsilon value for the MSE of the projection matrix estimation*/
- const float eps_;
+ float eps_;
/** \brief using only a subsample of points to calculate the projection matrix. pyramid_level_ = use down sampled cloud given by pyramid_level_*/
const unsigned pyramid_level_;
continue;
}
- Eigen::VectorXf model_coefficients;
- weight_sac.getModelCoefficients (model_coefficients);
+ Eigen::VectorXf model_coefficients = weight_sac.getModelCoefficients ();
model_coefficients[3] += std::numeric_limits<float>::epsilon ();
- weight_sac.getInliers (*support_indices);
+ *support_indices = weight_sac.getInliers ();
// the support_indices which are actually cut (if not locally constrain: cut_support_indices = support_indices
pcl::Indices cut_support_indices;
}
// Get the model inliers
- sac_->getInliers (inliers.indices);
+ inliers.indices = sac_->getInliers ();
// Get the model coefficients
- Eigen::VectorXf coeff (model_->getModelSize ());
- sac_->getModelCoefficients (coeff);
+ Eigen::VectorXf coeff = sac_->getModelCoefficients ();
// If the user needs optimized coefficients
if (optimize_coefficients_)
unsigned count_;
/** \brief The mean curvature of the region. */
- float curvature_;
+ float curvature_{0.0f};
public:
PCL_MAKE_ALIGNED_OPERATOR_NEW
{
// Compute eigenvalues and vectors using SVD
Eigen::JacobiSVD<Eigen::Matrix3f> svd (g.covariance, Eigen::ComputeFullU);
- // Store highest eigenvalue
- g.eigenvalue = svd.singularValues ()[0];
- // Store corresponding eigenvector
- g.eigenvector = svd.matrixU ().col (0);
+#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
+ if (svd.info() == Eigen::ComputationInfo::Success) {
+#endif
+ // Store highest eigenvalue
+ g.eigenvalue = svd.singularValues ()[0];
+ // Store corresponding eigenvector
+ g.eigenvector = svd.matrixU ().col (0);
+#if EIGEN_VERSION_AT_LEAST(3, 4, 0)
+ } else {
+ PCL_WARN("[grabcut::GaussianFitter::fit] Eigen::JacobiSVD was unsuccessful!\n");
+ }
+#endif
}
}
}
GLenum error = glGetError();
while (error != GL_NO_ERROR) {
last_error = error;
- std::cout << "Error: OpenGL: " << gluErrorString(error) << std::endl;
+ switch (error) {
+ case GL_INVALID_ENUM:
+ std::cout << "Error: OpenGL: GL_INVALID_ENUM" << std::endl;
+ break;
+ case GL_INVALID_VALUE:
+ std::cout << "Error: OpenGL: GL_INVALID_VALUE" << std::endl;
+ break;
+ case GL_INVALID_OPERATION:
+ std::cout << "Error: OpenGL: GL_INVALID_OPERATION" << std::endl;
+ break;
+ case GL_STACK_OVERFLOW:
+ std::cout << "Error: OpenGL: GL_STACK_OVERFLOW" << std::endl;
+ break;
+ case GL_STACK_UNDERFLOW:
+ std::cout << "Error: OpenGL: GL_STACK_UNDERFLOW" << std::endl;
+ break;
+ case GL_OUT_OF_MEMORY:
+ std::cout << "Error: OpenGL: GL_OUT_OF_MEMORY" << std::endl;
+ break;
+ default:
+ std::cout << "Error: OpenGL: Unknown error" << std::endl;
+ }
error = glGetError();
}
return last_error;
int OctNode<NodeData,Real>::maxDepth(void) const{
if(!children){return 0;}
else{
- int c,d;
+ int c = std::numeric_limits<int>::lowest();
for(int i=0;i<Cube::CORNERS;i++){
- d=children[i].maxDepth();
- if(!i || d>c){c=d;}
+ const int d=children[i].maxDepth();
+ if(d>c){c=d;}
}
return c+1;
}
template <typename PointInT> void
pcl::ConcaveHull<PointInT>::getHullPointIndices (pcl::PointIndices &hull_point_indices) const
{
+ if (!keep_information_) {
+ PCL_WARN("[pcl::ConcaveHull::getHullPointIndices] You need to call setKeepInformation(true) before reconstructing!\n");
+ }
hull_point_indices = hull_indices_;
}
// 2D coordinates of points
const Eigen::Vector2f uvn_nn_qp_zero = Eigen::Vector2f::Zero();
- Eigen::Vector2f uvn_current;
- Eigen::Vector2f uvn_prev;
- Eigen::Vector2f uvn_next;
// initializing fields
already_connected_ = false; // see declaration for comments :P
p.y = pos[1];
p.z = pos[2];
- pcl::Indices nn_indices;
- std::vector<float> nn_dists;
+ pcl::Indices nn_indices (1);
+ std::vector<float> nn_dists (1);
tree_->nearestKSearch (p, 1, nn_indices, nn_dists);
const auto input_index = nn_indices.front ();
// Computing coefficients
const Eigen::MatrixXd P_weight = P * weight_vec.asDiagonal(); // size will be (nr_coeff_, nn_indices.size ());
- P_weight_Pt = P_weight * P.transpose ();
- c_vec = P_weight * f_vec;
+ P_weight_Pt.noalias() = P_weight * P.transpose ();
+ c_vec.noalias() = P_weight * f_vec;
P_weight_Pt.llt ().solveInPlace (c_vec);
}
}
return false;
if ( i0 == i1 && w0 != w1 )
return false;
- if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) )
+ if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) )
return false;
if (i0 > i1)
{
{
if ( !ON_IsValid(w0) || !ON_IsValid(w1) || 0.0 == w0 || 0.0 == w1 )
return false;
- if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) )
+ if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) )
return false;
if (!ClampEnd(2))
if ( !ON_IsValid(w0) || !ON_IsValid(w1) || 0.0 == w0 || 0.0 == w1 )
return false;
- if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) )
+ if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w1 < 0.0) )
return false;
if ( !ON_ClampKnotVector( dim+1, order, cv_count, cvstride, cv, knot, 2 ) )
double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
Eigen::Vector2d params;
- Eigen::Vector3d point;
double points[3];
double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
Eigen::Vector2d params;
- Eigen::Vector3d point;
double points[3];
double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
Eigen::Vector2d params;
- Eigen::Vector3d point;
double points[3];
SequentialFitter::is_back_facing (const Eigen::Vector3d &v0, const Eigen::Vector3d &v1, const Eigen::Vector3d &v2,
const Eigen::Vector3d &)
{
- Eigen::Vector3d e1, e2, e3;
+ Eigen::Vector3d e1, e2;
e1 = v1 - v0;
e2 = v2 - v0;
for (auto &v : *cloud)
{
- Eigen::Vector3d tu, tv;
-
double point[3];
nurbs.Evaluate (v.x, v.y, 0, 3, point);
PointXYZ point;
Indices indices;
Eigen::Vector3f centroid = Eigen::Vector3f::Random();
- Eigen::Vector3f major_axis;
- Eigen::Vector3f middle_axis;
- Eigen::Vector3f minor_axis;
Eigen::Matrix<float, 3, 1> obb_position;
Eigen::Matrix<float, 3, 1> obb_dimensions;
Eigen::Matrix3f obb_rotational_matrix= Eigen::Matrix3f::Random();
}
}
+namespace custom {
+ struct MyPoint {
+ float x, y, z, w;
+ double intensity;
+ };
+ struct MyPoint2 {
+ double x, y, z, w;
+ };
+}
+
+POINT_CLOUD_REGISTER_POINT_STRUCT (custom::MyPoint,
+ (float, x, x)
+ (float, y, y)
+ (float, z, z)
+ (double, intensity, intensity)
+)
+POINT_CLOUD_REGISTER_POINT_STRUCT (custom::MyPoint2,
+ (double, x, x)
+ (double, y, y)
+ (double, z, z)
+)
+
+TEST(CopyPointTest, SameFieldNameDifferentDatatype)
+{
+ // in p1 the intensity field is double, while in p2 it is float
+ custom::MyPoint p1;
+ pcl::PointXYZI p2;
+ p1.x = 1.0;
+ p1.y = 2.0;
+ p1.z = 3.0;
+ p1.intensity = 5.0;
+ pcl::copyPoint(p1, p2);
+ EXPECT_EQ(p1.x, p2.x);
+ EXPECT_EQ(p1.y, p2.y);
+ EXPECT_EQ(p1.z, p2.z);
+ EXPECT_EQ(p1.intensity, p2.intensity);
+
+ // in p3 xyz are float, while in p4 they are double
+ pcl::PointXYZ p3;
+ custom::MyPoint2 p4;
+ p3.x = 10.0;
+ p3.y = 11.0;
+ p3.z = 12.0;
+ pcl::copyPoint(p3, p4);
+ EXPECT_EQ(p3.x, p4.x);
+ EXPECT_EQ(p3.y, p4.y);
+ EXPECT_EQ(p3.z, p4.z);
+}
+
int
main (int argc, char **argv)
{
#include <pcl/io/pcd_grabber.h>
#include <pcl/io/image_grabber.h>
+#include <chrono>
#include <string>
#include <thread>
#include <vector>
remove ("test_autoio.ifs");
}
+TEST(PCL, IFS)
+{
+ // Write a cloud to an IFS file and check if it is the same after loading
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
+ cloud->push_back(pcl::PointXYZ(1.0, 2.0, 3.0));
+ cloud->push_back(pcl::PointXYZ(4.0, 5.0, 6.0));
+
+ pcl::io::saveIFSFile("test.ifs", *cloud);
+
+ pcl::PointCloud<pcl::PointXYZ>::Ptr loaded(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::io::loadIFSFile("test.ifs", *loaded);
+
+ EXPECT_EQ(cloud->size(), loaded->size());
+ for (size_t i = 0; i < cloud->size(); ++i)
+ {
+ const auto& src = cloud->points[i];
+ const auto& dst = loaded->points[i];
+ EXPECT_EQ(src.x, dst.x);
+ EXPECT_EQ(src.y, dst.y);
+ EXPECT_EQ(src.z, dst.z);
+ }
+ remove("test.ifs");
+}
+
/* ---[ */
int
main (int argc, char** argv)
FILES test_flann_search.cpp
LINK_WITH pcl_gtest pcl_search pcl_kdtree)
+if(TARGET nanoflann::nanoflann)
+PCL_ADD_TEST(kdtree_nanoflann_search test_kdtree_nanoflann_search
+ FILES test_kdtree_nanoflann.cpp
+ LINK_WITH pcl_gtest pcl_common pcl_search pcl_io pcl_features
+ ARGUMENTS "${PCL_SOURCE_DIR}/test/bun0.pcd")
+endif()
+
PCL_ADD_TEST(organized_neighbor test_organized_search
FILES test_organized.cpp
LINK_WITH pcl_gtest pcl_search pcl_kdtree)
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2025-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#define PCL_NO_PRECOMPILE 1 // for MyPoint instantiations
+#include <pcl/common/distances.h>
+#include <pcl/common/io.h> // for copyPointCloud
+#include <pcl/common/time.h>
+#include <pcl/features/fpfh.h>
+#include <pcl/features/normal_3d.h>
+#include <pcl/io/pcd_io.h>
+#include <pcl/search/kdtree.h> // for pcl::search::KdTree
+#include <pcl/search/kdtree_nanoflann.h> // for pcl::search::KdTreeNanoflann
+#include <pcl/test/gtest.h>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
+
+#include <iostream>
+
+namespace pcl_tests {
+inline double
+squared_point_distance(const pcl::Narf36& p1, const pcl::Narf36& p2)
+{
+ double dist = 0.0;
+ for (std::size_t i = 0; i < 36; ++i)
+ dist += std::pow(static_cast<double>(p1.descriptor[i]) -
+ static_cast<double>(p2.descriptor[i]),
+ 2);
+ return dist;
+}
+} // namespace pcl_tests
+
+using namespace pcl;
+
+// many of the tests are copied and adapted form test/search/test_flann_search.cpp and
+// test/kdtree/test_kdtree.cpp
+
+PointCloud<PointXYZ> cloud, cloud_big, bun0_cloud;
+
+void
+init()
+{
+ float resolution = 0.1f;
+ for (float z = -0.5f; z <= 0.5f; z += resolution)
+ for (float y = -0.5f; y <= 0.5f; y += resolution)
+ for (float x = -0.5f; x <= 0.5f; x += resolution)
+ cloud.emplace_back(static_cast<float>(rand()) / (RAND_MAX + 1.0) - 0.5,
+ static_cast<float>(rand()) / (RAND_MAX + 1.0) - 0.5,
+ static_cast<float>(rand()) / (RAND_MAX + 1.0) - 0.5);
+ cloud.width = cloud.size();
+ cloud.height = 1;
+
+ // Randomly create a new point cloud, use points.emplace_back
+ cloud_big.width = 640 * 480;
+ cloud_big.height = 1;
+ for (std::size_t i = 0; i < cloud_big.width * cloud_big.height; ++i)
+ cloud_big.points.emplace_back(static_cast<float>(1024 * rand() / (RAND_MAX + 1.0)),
+ static_cast<float>(1024 * rand() / (RAND_MAX + 1.0)),
+ static_cast<float>(1024 * rand() / (RAND_MAX + 1.0)));
+}
+
+TEST(PCL, KdTreeNanoflann_nearestKSearch)
+{
+ auto kdtree = pcl::make_shared<pcl::search::KdTreeNanoflann<PointXYZ>>();
+ kdtree->setInputCloud(cloud.makeShared());
+ EXPECT_EQ(kdtree->getEpsilon(), 0.0f);
+ kdtree->setEpsilon(1.23f);
+ EXPECT_EQ(kdtree->getEpsilon(), 1.23f);
+ kdtree->setEpsilon(0.0f);
+ PointXYZ test_point(0.01f, 0.01f, 0.01f);
+ unsigned int no_of_neighbors = 20;
+ std::multimap<float, int> sorted_brute_force_result;
+ for (std::size_t i = 0; i < cloud.size(); ++i) {
+ float distance = euclideanDistance(cloud[i], test_point);
+ sorted_brute_force_result.insert(std::make_pair(distance, static_cast<int>(i)));
+ }
+ float max_dist = 0.0f;
+ unsigned int counter = 0;
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && counter < no_of_neighbors;
+ ++it) {
+ max_dist = std::max(max_dist, it->first);
+ ++counter;
+ }
+
+ pcl::Indices k_indices;
+ k_indices.resize(no_of_neighbors);
+ std::vector<float> k_distances;
+ k_distances.resize(no_of_neighbors);
+
+ kdtree->nearestKSearch(test_point, no_of_neighbors, k_indices, k_distances);
+
+ EXPECT_EQ(k_indices.size(), no_of_neighbors);
+
+ // Check if all found neighbors have distance smaller than max_dist
+ for (const auto& k_index : k_indices) {
+ const PointXYZ& point = cloud[k_index];
+ bool ok = euclideanDistance(test_point, point) <= max_dist;
+ if (!ok)
+ ok = (std::abs(euclideanDistance(test_point, point)) - max_dist) <= 1e-6;
+ EXPECT_TRUE(ok);
+ }
+
+ kdtree->setUseRKNN(true);
+ pcl::Indices k_indices_rknn;
+ std::vector<float> k_distances_rknn;
+ // first test with search radius bigger than farthest neighbor, results should be the
+ // same
+ kdtree->radiusSearch(test_point,
+ max_dist + std::numeric_limits<float>::epsilon(),
+ k_indices_rknn,
+ k_distances_rknn,
+ no_of_neighbors);
+ EXPECT_EQ(k_indices_rknn.size(), k_indices.size());
+ EXPECT_EQ(k_distances_rknn.size(), k_distances.size());
+ for (std::size_t i = 0;
+ i < std::min<std::size_t>(k_indices.size(), k_indices_rknn.size());
+ ++i) {
+ EXPECT_EQ(k_indices[i], k_indices_rknn[i]);
+ EXPECT_EQ(k_distances[i], k_distances_rknn[i]);
+ }
+ // then test with search radius slightly smaller than farthest neighbor, should have
+ // one neighbor less
+ kdtree->radiusSearch(test_point,
+ max_dist - std::numeric_limits<float>::epsilon(),
+ k_indices_rknn,
+ k_distances_rknn,
+ no_of_neighbors);
+ EXPECT_EQ(k_indices_rknn.size() + 1, k_indices.size());
+ EXPECT_EQ(k_distances_rknn.size() + 1, k_distances.size());
+ for (std::size_t i = 0;
+ i < std::min<std::size_t>(k_indices.size(), k_indices_rknn.size());
+ ++i) {
+ EXPECT_EQ(k_indices[i], k_indices_rknn[i]);
+ EXPECT_EQ(k_distances[i], k_distances_rknn[i]);
+ }
+}
+
+/* Test the templated NN search (for different query point types) */
+TEST(PCL, KdTreeNanoflannSearch_differentPointT)
+{
+
+ unsigned int no_of_neighbors = 20;
+
+ pcl::search::KdTreeNanoflann<PointXYZ> kdtree;
+ kdtree.setInputCloud(cloud_big.makeShared());
+
+ PointCloud<PointXYZRGB> cloud_rgb;
+
+ copyPointCloud(cloud_big, cloud_rgb);
+
+ std::vector<std::vector<float>> dists;
+ std::vector<pcl::Indices> indices;
+ kdtree.nearestKSearchT(cloud_rgb, pcl::Indices(), no_of_neighbors, indices, dists);
+
+ pcl::Indices k_indices;
+ k_indices.resize(no_of_neighbors);
+ std::vector<float> k_distances;
+ k_distances.resize(no_of_neighbors);
+
+ for (std::size_t i = 0; i < cloud_rgb.size(); ++i) {
+ kdtree.nearestKSearch(cloud_big[i], no_of_neighbors, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), indices[i].size());
+ EXPECT_EQ(k_distances.size(), dists[i].size());
+ for (std::size_t j = 0; j < no_of_neighbors; j++) {
+ EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]);
+ }
+ }
+}
+
+/* Test for KdTreeNanoflann nearestKSearch with multiple query points */
+TEST(PCL, KdTreeNanoflann_multipointKnnSearch)
+{
+
+ unsigned int no_of_neighbors = 20;
+
+ pcl::search::KdTreeNanoflann<PointXYZ> kdtree;
+ kdtree.setInputCloud(cloud_big.makeShared());
+
+ std::vector<std::vector<float>> dists;
+ std::vector<pcl::Indices> indices;
+ kdtree.nearestKSearch(cloud_big, pcl::Indices(), no_of_neighbors, indices, dists);
+
+ pcl::Indices k_indices;
+ k_indices.resize(no_of_neighbors);
+ std::vector<float> k_distances;
+ k_distances.resize(no_of_neighbors);
+
+ for (std::size_t i = 0; i < cloud_big.size(); ++i) {
+ kdtree.nearestKSearch(cloud_big[i], no_of_neighbors, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), indices[i].size());
+ EXPECT_EQ(k_distances.size(), dists[i].size());
+ for (std::size_t j = 0; j < no_of_neighbors; j++) {
+ EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]);
+ }
+ }
+}
+
+/* Test for KdTreeNanoflann nearestKSearch with multiple query points */
+TEST(PCL, KdTreeNanoflann_knnByIndex)
+{
+
+ unsigned int no_of_neighbors = 3;
+
+ pcl::search::KdTreeNanoflann<PointXYZ> kdtree;
+ kdtree.setInputCloud(cloud_big.makeShared());
+
+ std::vector<std::vector<float>> dists;
+ std::vector<pcl::Indices> indices;
+ pcl::Indices query_indices;
+ for (std::size_t i = 0; i < cloud_big.size(); i += 2) {
+ query_indices.push_back(static_cast<int>(i));
+ }
+ kdtree.nearestKSearch(cloud_big, query_indices, no_of_neighbors, indices, dists);
+
+ pcl::Indices k_indices;
+ k_indices.resize(no_of_neighbors);
+ std::vector<float> k_distances;
+ k_distances.resize(no_of_neighbors);
+
+ for (std::size_t i = 0; i < query_indices.size(); ++i) {
+ kdtree.nearestKSearch(cloud_big[2 * i], no_of_neighbors, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), indices[i].size());
+ EXPECT_EQ(k_distances.size(), dists[i].size());
+ for (std::size_t j = 0; j < no_of_neighbors; j++) {
+ EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]);
+ }
+ kdtree.nearestKSearch(
+ cloud_big, query_indices[i], no_of_neighbors, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), indices[i].size());
+ EXPECT_EQ(k_distances.size(), dists[i].size());
+ for (std::size_t j = 0; j < no_of_neighbors; j++) {
+ EXPECT_TRUE(k_indices[j] == indices[i][j] || k_distances[j] == dists[i][j]);
+ }
+ }
+}
+
+TEST(PCL, KdTreeNanoflann_compareToKdTreeFlann)
+{
+
+ int no_of_neighbors = 3;
+ pcl::Indices k_indices;
+ k_indices.resize(no_of_neighbors);
+ std::vector<float> k_distances;
+ k_distances.resize(no_of_neighbors);
+
+ pcl::search::Search<PointXYZ>*nanoflann_search, *kdtree_search;
+
+ PointCloud<PointXYZ>::Ptr pc = cloud_big.makeShared();
+ {
+ ScopeTime scopeTime("KdTreeNanoflann build");
+ nanoflann_search = new pcl::search::KdTreeNanoflann<PointXYZ>;
+ nanoflann_search->setInputCloud(pc);
+ }
+
+ {
+ ScopeTime scopeTime("kdtree build");
+ kdtree_search = new pcl::search::KdTree<PointXYZ>();
+ kdtree_search->setInputCloud(pc);
+ }
+
+ {
+ ScopeTime scopeTime("KdTreeNanoflann nearestKSearch");
+ for (const auto& point : cloud_big.points)
+ nanoflann_search->nearestKSearch(point, no_of_neighbors, k_indices, k_distances);
+ }
+ {
+ ScopeTime scopeTime("kd tree nearestKSearch");
+ for (const auto& point : cloud_big.points)
+ kdtree_search->nearestKSearch(point, no_of_neighbors, k_indices, k_distances);
+ }
+
+ std::vector<pcl::Indices> indices_nanoflann;
+ std::vector<std::vector<float>> dists_nanoflann;
+ std::vector<pcl::Indices> indices_tree;
+ std::vector<std::vector<float>> dists_tree;
+ indices_nanoflann.resize(cloud_big.size());
+ dists_nanoflann.resize(cloud_big.size());
+ indices_tree.resize(cloud_big.size());
+ dists_tree.resize(cloud_big.size());
+ for (std::size_t i = 0; i < cloud_big.size(); ++i) {
+ indices_nanoflann[i].resize(no_of_neighbors);
+ dists_nanoflann[i].resize(no_of_neighbors);
+ indices_tree[i].resize(no_of_neighbors);
+ dists_tree[i].resize(no_of_neighbors);
+ }
+
+ {
+ ScopeTime scopeTime("KdTreeNanoflann multi nearestKSearch");
+ nanoflann_search->nearestKSearch(
+ cloud_big, pcl::Indices(), no_of_neighbors, indices_nanoflann, dists_nanoflann);
+ }
+ {
+ ScopeTime scopeTime("kd tree multi nearestKSearch");
+ kdtree_search->nearestKSearch(
+ cloud_big, pcl::Indices(), no_of_neighbors, indices_tree, dists_tree);
+ }
+
+ ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices_nanoflann.size(), indices_tree.size());
+ ASSERT_EQ(indices_nanoflann.size(), dists_tree.size());
+
+ for (std::size_t i = 0; i < indices_nanoflann.size(); i++) {
+ ASSERT_EQ(indices_nanoflann[i].size(), no_of_neighbors);
+ ASSERT_EQ(indices_tree[i].size(), no_of_neighbors);
+ ASSERT_EQ(dists_nanoflann[i].size(), no_of_neighbors);
+ ASSERT_EQ(dists_tree[i].size(), no_of_neighbors);
+ for (int j = 0; j < no_of_neighbors; j++) {
+
+ ASSERT_TRUE(indices_nanoflann[i][j] == indices_tree[i][j] ||
+ dists_nanoflann[i][j] == dists_tree[i][j]);
+ }
+ }
+
+ pcl::Indices query_indices;
+ for (std::size_t i = 0; i < cloud_big.size(); i += 2)
+ query_indices.push_back(static_cast<int>(i));
+
+ {
+ ScopeTime scopeTime("KdTreeNanoflann multi nearestKSearch with indices");
+ nanoflann_search->nearestKSearch(
+ cloud_big, query_indices, no_of_neighbors, indices_nanoflann, dists_nanoflann);
+ }
+ {
+ ScopeTime scopeTime("kd tree multi nearestKSearch with indices");
+ kdtree_search->nearestKSearch(
+ cloud_big, query_indices, no_of_neighbors, indices_tree, dists_tree);
+ }
+ ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices_nanoflann.size(), indices_tree.size());
+ ASSERT_EQ(indices_nanoflann.size(), dists_tree.size());
+
+ for (std::size_t i = 0; i < indices_nanoflann.size(); i++) {
+ ASSERT_EQ(indices_nanoflann[i].size(), no_of_neighbors);
+ ASSERT_EQ(indices_tree[i].size(), no_of_neighbors);
+ ASSERT_EQ(dists_nanoflann[i].size(), no_of_neighbors);
+ ASSERT_EQ(dists_tree[i].size(), no_of_neighbors);
+ for (int j = 0; j < no_of_neighbors; j++) {
+ ASSERT_TRUE(indices_nanoflann[i][j] == indices_tree[i][j] ||
+ dists_nanoflann[i][j] == dists_tree[i][j]);
+ }
+ }
+
+ delete nanoflann_search;
+ delete kdtree_search;
+}
+
+// test with FPFHSignature33
+TEST(PCL, KdTreeNanoflann_features)
+{
+ using FeatureT = FPFHSignature33;
+
+ // Create shared pointers
+ pcl::PointCloud<PointXYZ>::Ptr cloud_source_ptr;
+ cloud_source_ptr = bun0_cloud.makeShared();
+
+ // first estimate normals
+ PointCloud<Normal>::Ptr normals(new PointCloud<Normal>);
+ pcl::NormalEstimation<PointXYZ, Normal> norm_est;
+ norm_est.setRadiusSearch(0.05);
+ norm_est.setInputCloud(cloud_source_ptr);
+ norm_est.compute(*normals);
+
+ // then estimate features
+ PointCloud<FeatureT>::Ptr features_source(new PointCloud<FeatureT>);
+ pcl::FPFHEstimation<PointXYZ, Normal, FeatureT> fpfh_est;
+ fpfh_est.setRadiusSearch(0.05);
+ fpfh_est.setInputCloud(cloud_source_ptr);
+ fpfh_est.setInputNormals(normals);
+ fpfh_est.compute(*features_source);
+
+ pcl::search::KdTree<FeatureT> kdtree;
+ kdtree.setInputCloud(features_source);
+
+ pcl::search::KdTreeNanoflann<FeatureT, -1> kdtree_nanoflann;
+ kdtree_nanoflann.setInputCloud(features_source);
+
+ pcl::Indices indices, indices_nanoflann;
+ std::vector<float> dists, dists_nanoflann;
+
+ // test nearestKSearch
+ ASSERT_TRUE(std::isfinite((*features_source)[10].histogram[0]));
+ kdtree.nearestKSearch((*features_source)[10], 10, indices, dists);
+ kdtree_nanoflann.nearestKSearch(
+ (*features_source)[10], 10, indices_nanoflann, dists_nanoflann);
+ ASSERT_EQ(indices.size(), indices_nanoflann.size());
+ ASSERT_EQ(dists.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices.size(), dists.size());
+ for (std::size_t i = 0; i < indices.size(); ++i) {
+ EXPECT_EQ(indices[i], indices_nanoflann[i]);
+ EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4);
+ }
+
+ ASSERT_TRUE(std::isfinite((*features_source)[99].histogram[0]));
+ kdtree.nearestKSearch((*features_source)[99], 5, indices, dists);
+ kdtree_nanoflann.nearestKSearch(
+ (*features_source)[99], 5, indices_nanoflann, dists_nanoflann);
+ ASSERT_EQ(indices.size(), indices_nanoflann.size());
+ ASSERT_EQ(dists.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices.size(), dists.size());
+ for (std::size_t i = 0; i < indices.size(); ++i) {
+ EXPECT_EQ(indices[i], indices_nanoflann[i]);
+ EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4);
+ }
+}
+
+// test with Narf36, because it has a non-trivial point representation
+TEST(PCL, KdTreeNanoflann_Narf36)
+{
+ using FeatureT = pcl::Narf36;
+ auto feature_cloud = pcl::make_shared<pcl::PointCloud<FeatureT>>();
+ feature_cloud->resize(1000);
+ for (auto& feature : *feature_cloud) {
+ feature.x = 20.0 * rand() / RAND_MAX - 10.0;
+ feature.y = 20.0 * rand() / RAND_MAX - 10.0;
+ feature.z = 20.0 * rand() / RAND_MAX - 10.0;
+ feature.roll = M_PI * rand() / RAND_MAX;
+ feature.pitch = M_PI * rand() / RAND_MAX;
+ feature.yaw = M_PI * rand() / RAND_MAX;
+ for (float& desc : feature.descriptor) {
+ desc = 2.0 * rand() / RAND_MAX - 1.0;
+ }
+ }
+ pcl::search::KdTree<FeatureT> kdtree;
+ kdtree.setInputCloud(feature_cloud);
+
+ pcl::search::KdTreeNanoflann<FeatureT, 36> kdtree_nanoflann;
+ kdtree_nanoflann.setSortedResults(true);
+ kdtree_nanoflann.setInputCloud(feature_cloud);
+
+ pcl::Indices indices, indices_nanoflann;
+ std::vector<float> dists, dists_nanoflann;
+
+ // test nearestKSearch
+ for (std::size_t j = 0; j < feature_cloud->size(); ++j) {
+ const int k = static_cast<int>(99.0 * rand() / RAND_MAX + 1);
+ kdtree.nearestKSearch((*feature_cloud)[j], k, indices, dists);
+ kdtree_nanoflann.nearestKSearch(
+ (*feature_cloud)[j], k, indices_nanoflann, dists_nanoflann);
+ ASSERT_EQ(indices.size(), indices_nanoflann.size());
+ ASSERT_EQ(dists.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices.size(), dists.size());
+ ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size());
+ for (std::size_t i = 0; i < indices.size(); ++i) {
+ // sometimes, two neighbors have almost the same distance to the query point, but
+ // are switched due to limited floating point accuracy.
+ if ((i + 1) < indices.size() && indices[i] != indices_nanoflann[i] &&
+ indices[i + 1] != indices_nanoflann[i + 1] &&
+ (indices[i] == indices_nanoflann[i + 1] ||
+ indices[i + 1] == indices_nanoflann[i]) &&
+ std::abs(dists[i] - dists_nanoflann[i + 1]) < 1e-4 &&
+ std::abs(dists[i + 1] - dists_nanoflann[i]) < 1e-4) {
+ std::swap(indices[i], indices[i + 1]);
+ std::swap(dists[i], dists[i + 1]);
+ }
+ }
+ if (!indices.empty() && indices.back() != indices_nanoflann.back() &&
+ std::abs(dists.back() - dists_nanoflann.back()) < 1e-5 &&
+ std::abs(pcl_tests::squared_point_distance((*feature_cloud)[j],
+ (*feature_cloud)[indices.back()]) -
+ pcl_tests::squared_point_distance(
+ (*feature_cloud)[j], (*feature_cloud)[indices_nanoflann.back()])) <
+ 1e-5) {
+ indices_nanoflann.back() = indices.back();
+ }
+ for (std::size_t i = 0; i < indices.size(); ++i) {
+ EXPECT_EQ(indices[i], indices_nanoflann[i]);
+ EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4);
+ }
+ }
+
+ // test radiusSearch
+ for (std::size_t i = 0; i < feature_cloud->size(); ++i) {
+ const float radius = 3.5 + static_cast<float>(rand()) / RAND_MAX;
+ kdtree.radiusSearch((*feature_cloud)[i], radius, indices, dists);
+ kdtree_nanoflann.radiusSearch(
+ (*feature_cloud)[i], radius, indices_nanoflann, dists_nanoflann);
+ if (indices.size() > indices_nanoflann.size()) {
+ if (std::abs(pcl_tests::squared_point_distance((*feature_cloud)[i],
+ (*feature_cloud)[indices.back()]) -
+ static_cast<double>(radius) * static_cast<double>(radius)) < 1e-5) {
+ indices.pop_back();
+ dists.pop_back();
+ }
+ }
+ else if (indices.size() < indices_nanoflann.size()) {
+ if (std::abs(
+ pcl_tests::squared_point_distance(
+ (*feature_cloud)[i], (*feature_cloud)[indices_nanoflann.back()]) -
+ static_cast<double>(radius) * static_cast<double>(radius)) < 1e-5) {
+ indices_nanoflann.pop_back();
+ dists_nanoflann.pop_back();
+ }
+ }
+ ASSERT_EQ(indices.size(), indices_nanoflann.size());
+ ASSERT_EQ(dists.size(), dists_nanoflann.size());
+ ASSERT_EQ(indices.size(), dists.size());
+ ASSERT_EQ(indices_nanoflann.size(), dists_nanoflann.size());
+ for (std::size_t i = 0;
+ i < std::min<std::size_t>(indices.size(), indices_nanoflann.size());
+ ++i) {
+ // sometimes, two neighbors have almost the same distance to the query point, but
+ // are switched to due limited floating point accuracy.
+ if ((i + 1) < indices.size() && indices[i] != indices_nanoflann[i] &&
+ indices[i + 1] != indices_nanoflann[i + 1] &&
+ indices[i] == indices_nanoflann[i + 1] &&
+ indices[i + 1] == indices_nanoflann[i] &&
+ std::abs(dists[i] - dists_nanoflann[i + 1]) < 1e-4 &&
+ std::abs(dists[i + 1] - dists_nanoflann[i]) < 1e-4) {
+ std::swap(indices[i], indices[i + 1]);
+ std::swap(dists[i], dists[i + 1]);
+ }
+ EXPECT_EQ(indices[i], indices_nanoflann[i])
+ << "i=" << i << ", dists[i]=" << dists[i]
+ << ", dists_nanoflann[i]=" << dists_nanoflann[i] << std::endl;
+ ;
+ EXPECT_NEAR(dists[i], dists_nanoflann[i], 1e-4);
+ }
+ }
+}
+
+template <typename PointT>
+double
+manhattanDistance(const PointT& a, const PointT& b)
+{
+ return std::abs(static_cast<double>(a.x) - static_cast<double>(b.x)) +
+ std::abs(static_cast<double>(a.y) - static_cast<double>(b.y)) +
+ std::abs(static_cast<double>(a.z) - static_cast<double>(b.z));
+}
+
+// test with L1/manhattan distance instead of L2/euclidean distance
+TEST(PCL, KdTreeNanoflann_nearestKSearch_L1)
+{
+ pcl::search::KdTreeNanoflann<PointXYZ, 3, pcl::search::L1_Adaptor> kdtree_nanoflann;
+ kdtree_nanoflann.setInputCloud(bun0_cloud.makeShared());
+
+ kdtree_nanoflann.setSortedResults(true);
+ PointXYZ test_point = bun0_cloud[rand() % bun0_cloud.size()];
+ const unsigned int no_of_neighbors = 20;
+ std::multimap<double, int> sorted_brute_force_result;
+ for (std::size_t i = 0; i < bun0_cloud.size(); ++i) {
+ auto distance = manhattanDistance(bun0_cloud[i], test_point);
+ sorted_brute_force_result.emplace(distance, i);
+ }
+
+ pcl::Indices k_indices;
+ std::vector<float> k_distances;
+
+ EXPECT_EQ(no_of_neighbors,
+ kdtree_nanoflann.nearestKSearch(
+ test_point, no_of_neighbors, k_indices, k_distances));
+ EXPECT_EQ(k_indices.size(), no_of_neighbors);
+ EXPECT_EQ(k_distances.size(), no_of_neighbors);
+ unsigned int counter = 0;
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && counter < no_of_neighbors;
+ ++it, ++counter) {
+ EXPECT_EQ(k_indices[counter], it->second);
+ EXPECT_NEAR(k_distances[counter], it->first, 1e-6);
+ }
+
+ // test radius search
+ const float search_radius = 10 * std::next(sorted_brute_force_result.begin())->first;
+ kdtree_nanoflann.radiusSearch(test_point, search_radius, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), k_distances.size());
+ counter = 0;
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && it->first <= search_radius;
+ ++it, ++counter) {
+ // sometimes, two neighbors have almost the same distance to the query point, but
+ // are switched to due limited floating point accuracy.
+ if ((counter + 1) < k_indices.size() && k_indices[counter] != it->second &&
+ k_indices[counter + 1] != std::next(it)->second &&
+ k_indices[counter] == std::next(it)->second &&
+ k_indices[counter + 1] == it->second &&
+ std::abs(k_distances[counter] - std::next(it)->first) < 1e-6 &&
+ std::abs(k_distances[counter + 1] - it->first) < 1e-6) {
+ std::swap(k_indices[counter], k_indices[counter + 1]);
+ std::swap(k_distances[counter], k_distances[counter + 1]);
+ }
+ EXPECT_EQ(k_indices[counter], it->second);
+ EXPECT_NEAR(k_distances[counter], it->first, 1e-6);
+ }
+ EXPECT_EQ(k_indices.size(), counter);
+ // test unsorted radius search
+ kdtree_nanoflann.setSortedResults(false);
+ k_indices.clear();
+ k_distances.clear();
+ kdtree_nanoflann.radiusSearch(test_point, search_radius, k_indices, k_distances);
+ EXPECT_EQ(k_indices.size(), k_distances.size());
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && it->first <= search_radius;
+ ++it) {
+ auto pos = std::find(k_indices.begin(), k_indices.end(), it->second);
+ ASSERT_NE(pos, k_indices.end()); // must be found
+ EXPECT_NEAR(it->first, k_distances[std::distance(k_indices.begin(), pos)], 1e-6);
+ }
+}
+
+struct MyPoint : public PointXYZ {
+ MyPoint(float x, float y, float z)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+};
+
+class MyPointRepresentationXY : public PointRepresentation<MyPoint> {
+public:
+ MyPointRepresentationXY() { this->nr_dimensions_ = 2; }
+
+ void
+ copyToFloatArray(const MyPoint& p, float* out) const override
+ {
+ out[0] = p.x;
+ out[1] = p.y;
+ }
+};
+
+TEST(PCL, KdTreeNanoflann_setPointRepresentation)
+{
+ PointCloud<MyPoint>::Ptr random_cloud(new PointCloud<MyPoint>());
+ random_cloud->points.emplace_back(86.6f, 42.1f, 92.4f);
+ random_cloud->points.emplace_back(63.1f, 18.4f, 22.3f);
+ random_cloud->points.emplace_back(35.5f, 72.5f, 37.3f);
+ random_cloud->points.emplace_back(99.7f, 37.0f, 8.7f);
+ random_cloud->points.emplace_back(22.4f, 84.1f, 64.0f);
+ random_cloud->points.emplace_back(65.2f, 73.4f, 18.0f);
+ random_cloud->points.emplace_back(60.4f, 57.1f, 4.5f);
+ random_cloud->points.emplace_back(38.7f, 17.6f, 72.3f);
+ random_cloud->points.emplace_back(14.2f, 95.7f, 34.7f);
+ random_cloud->points.emplace_back(2.5f, 26.5f, 66.0f);
+
+ auto kdtree = pcl::make_shared<pcl::search::KdTreeNanoflann<MyPoint, -1>>();
+ kdtree->setInputCloud(random_cloud);
+ EXPECT_EQ(3, kdtree->getPointRepresentation()->getNumberOfDimensions());
+ MyPoint p(50.0f, 50.0f, 50.0f);
+
+ // Find k nearest neighbors
+ constexpr int k = 10;
+ pcl::Indices k_indices(k);
+ std::vector<float> k_distances(k);
+ kdtree->nearestKSearch(p, k, k_indices, k_distances);
+ for (int i = 0; i < k; ++i) {
+ // Compare to ground truth values, computed independently
+ static const int gt_indices[10] = {2, 7, 5, 1, 4, 6, 9, 0, 8, 3};
+ static const float gt_distances[10] = {877.8f,
+ 1674.7f,
+ 1802.6f,
+ 1937.5f,
+ 2120.6f,
+ 2228.8f,
+ 3064.5f,
+ 3199.7f,
+ 3604.2f,
+ 4344.8f};
+ EXPECT_EQ(k_indices[i], gt_indices[i]);
+ EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1);
+ }
+
+ // Find k nearest neighbors with a different point representation
+ pcl::search::KdTreeNanoflann<MyPoint, -1>::PointRepresentationConstPtr ptrep(
+ new MyPointRepresentationXY);
+ kdtree->setPointRepresentation(ptrep);
+ EXPECT_EQ(2, kdtree->getPointRepresentation()->getNumberOfDimensions());
+ kdtree->nearestKSearch(p, k, k_indices, k_distances);
+ for (int i = 0; i < k; ++i) {
+ // Compare to ground truth values, computed independently
+ static const int gt_indices[10] = {6, 2, 5, 1, 7, 0, 4, 3, 9, 8};
+ static const float gt_distances[10] = {158.6f,
+ 716.5f,
+ 778.6f,
+ 1170.2f,
+ 1177.5f,
+ 1402.0f,
+ 1924.6f,
+ 2639.1f,
+ 2808.5f,
+ 3370.1f};
+ EXPECT_EQ(k_indices[i], gt_indices[i]);
+ EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1);
+ }
+
+ // Go back to the default, this time with the values rescaled
+ DefaultPointRepresentation<MyPoint> point_rep;
+ float alpha[3] = {1.0f, 2.0f, 3.0f};
+ point_rep.setRescaleValues(alpha);
+ kdtree->setPointRepresentation(point_rep.makeShared());
+ EXPECT_EQ(3, kdtree->getPointRepresentation()->getNumberOfDimensions());
+ kdtree->nearestKSearch(p, k, k_indices, k_distances);
+ for (int i = 0; i < k; ++i) {
+ // Compare to ground truth values, computed independently
+ static const int gt_indices[10] = {2, 9, 4, 7, 1, 5, 8, 0, 3, 6};
+ static const float gt_distances[10] = {3686.9f,
+ 6769.2f,
+ 7177.0f,
+ 8802.3f,
+ 11071.5f,
+ 11637.3f,
+ 11742.4f,
+ 17769.0f,
+ 18497.3f,
+ 18942.0f};
+ EXPECT_EQ(k_indices[i], gt_indices[i]);
+ EXPECT_NEAR(k_distances[i], gt_distances[i], 0.1);
+ }
+}
+
+// test with nanoflann::KDTreeSingleIndexDynamicAdaptor (allows to dynamically
+// add/remove points)
+TEST(PCL, KdTreeNanoflann_dynamic)
+{
+ using Distance = pcl::search::L2_Simple_Adaptor;
+ constexpr std::int32_t Dim = 3;
+ pcl::search::KdTreeNanoflann<PointXYZ,
+ Dim,
+ Distance,
+ nanoflann::KDTreeSingleIndexDynamicAdaptor<
+ Distance,
+ pcl::search::internal::PointCloudAdaptor<float>,
+ Dim,
+ pcl::index_t>>
+ kdtree_nanoflann;
+ kdtree_nanoflann.setSortedResults(true);
+ auto input_cloud = bun0_cloud.makeShared();
+ input_cloud->reserve(input_cloud->size() + 1); // reserve space for one more point
+ kdtree_nanoflann.setInputCloud(input_cloud);
+
+ pcl::PointXYZ test_point = (*input_cloud)[rand() % input_cloud->size()];
+ const unsigned int no_of_neighbors = 20;
+ std::multimap<double, int> sorted_brute_force_result;
+ for (std::size_t i = 0; i < input_cloud->size(); ++i) {
+ auto distance = squaredEuclideanDistance((*input_cloud)[i], test_point);
+ sorted_brute_force_result.emplace(distance, i);
+ }
+
+ pcl::Indices k_indices;
+ std::vector<float> k_distances;
+
+ EXPECT_EQ(no_of_neighbors,
+ kdtree_nanoflann.nearestKSearch(
+ test_point, no_of_neighbors, k_indices, k_distances));
+ EXPECT_EQ(k_indices.size(), no_of_neighbors);
+ EXPECT_EQ(k_distances.size(), no_of_neighbors);
+ unsigned int counter = 0;
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && counter < no_of_neighbors;
+ ++it, ++counter) {
+ EXPECT_EQ(k_indices[counter], it->second);
+ EXPECT_NEAR(k_distances[counter], it->first, 1e-6);
+ }
+
+ kdtree_nanoflann.getNanoflannTree()->removePoint(k_indices[0]);
+ input_cloud->push_back(test_point);
+ kdtree_nanoflann.getNanoflannTree()->addPoints(input_cloud->size() - 1,
+ input_cloud->size() - 1);
+ sorted_brute_force_result.erase(sorted_brute_force_result.begin());
+ sorted_brute_force_result.emplace(0.0, input_cloud->size() - 1);
+
+ EXPECT_EQ(no_of_neighbors,
+ kdtree_nanoflann.nearestKSearch(
+ test_point, no_of_neighbors, k_indices, k_distances));
+ EXPECT_EQ(k_indices.size(), no_of_neighbors);
+ EXPECT_EQ(k_distances.size(), no_of_neighbors);
+ counter = 0;
+ for (auto it = sorted_brute_force_result.begin();
+ it != sorted_brute_force_result.end() && counter < no_of_neighbors;
+ ++it, ++counter) {
+ EXPECT_EQ(k_indices[counter], it->second);
+ EXPECT_NEAR(k_distances[counter], it->first, 1e-6);
+ }
+}
+
+int
+main(int argc, char** argv)
+{
+ const auto seed = time(nullptr);
+ std::cout << "seed=" << seed << std::endl;
+ srand(seed);
+ testing::InitGoogleTest(&argc, argv);
+ init();
+
+ if (argc < 2 || pcl::io::loadPCDFile(argv[1], bun0_cloud) < 0) {
+ std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its "
+ "path to the test."
+ << std::endl;
+ return (-1);
+ }
+
+ return (RUN_ALL_TESTS());
+}
#include <pcl/search/brute_force.h>
#include <pcl/search/kdtree.h>
#include <pcl/search/flann_search.h>
+#include <pcl/search/kdtree_nanoflann.h>
#include <pcl/search/organized.h>
#include <pcl/search/octree.h>
#include <pcl/io/pcd_io.h>
/** \brief instance of FlannSearch search method to be tested*/
pcl::search::FlannSearch<pcl::PointXYZ> FlannSearch;
+#if PCL_HAS_NANOFLANN
+pcl::search::KdTreeNanoflann<pcl::PointXYZ> KDTreeNanoflann;
+#endif
+
/** \brief instance of Octree search method to be tested*/
pcl::search::Octree<pcl::PointXYZ> octree_search (0.1);
brute_force.setSortedResults (true);
KDTree.setSortedResults (true);
+#if PCL_HAS_NANOFLANN
+ KDTreeNanoflann.setSortedResults (true);
+#endif
octree_search.setSortedResults (true);
organized.setSortedResults (true);
unorganized_search_methods.push_back (&brute_force);
unorganized_search_methods.push_back (&KDTree);
unorganized_search_methods.push_back (&FlannSearch);
+#if PCL_HAS_NANOFLANN
+ unorganized_search_methods.push_back (&KDTreeNanoflann);
+#endif
unorganized_search_methods.push_back (&octree_search);
organized_search_methods.push_back (&brute_force);
organized_search_methods.push_back (&KDTree);
organized_search_methods.push_back (&FlannSearch);
+#if PCL_HAS_NANOFLANN
+ organized_search_methods.push_back (&KDTreeNanoflann);
+#endif
organized_search_methods.push_back (&octree_search);
organized_search_methods.push_back (&organized);
#include <vtkHedgeHog.h>
#include <vtkMatrix4x4.h>
#include <algorithm>
+#include <chrono>
#include <cstdio>
#include <thread>
#include <vector>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkGlyph3D.h>
+#include <chrono>
#include <cstdio>
#include <thread>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkHedgeHog.h>
+#include <chrono>
#include <cstdio>
#include <thread>
#include <vtkRenderWindow.h>
#include <vector>
#include <list>
+#include <chrono>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vtkCubeSource.h>
#include <vtkPointData.h>
#include <vector>
+#include <chrono>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkTransform.h>
+#include <chrono>
#include <cstdio>
#include <list>
#include <thread>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkHedgeHog.h>
+#include <chrono>
#include <cstdio>
#include <thread>
RandomSampleConsensus<PointXYZ> sac (model, threshold);
sac.setMaxIterations (max_iterations);
bool res = sac.computeModel ();
-
- pcl::Indices inliers;
- sac.getInliers (inliers);
- Eigen::VectorXf coefficients;
- sac.getModelCoefficients (coefficients);
+
+ auto inliers = sac.getInliers ();
+ Eigen::VectorXf coefficients = sac.getModelCoefficients ();
if (!res || inliers.empty ())
{
return;
}
sac.refineModel (2, 50);
- sac.getInliers (inliers);
- sac.getModelCoefficients (coefficients);
+ inliers = sac.getInliers ();
+ coefficients = sac.getModelCoefficients ();
print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms, plane has : "); print_value ("%lu", inliers.size ()); print_info (" points]\n");
#pragma once
+#include <chrono>
#include <thread>
~PCLVisualizerInteractorStyle () override = default;
// this macro defines Superclass, the isA functionality and the safe downcast method
- vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick);
+ vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick)
/** \brief Initialization routine. Must be called before anything else. */
virtual void
view_mat.block <1, 3> (2, 0) = -zAxis;
view_mat.row (3) << 0, 0, 0, 1;
- view_mat.block <3, 1> (0, 3) = view_mat.topLeftCorner<3, 3> () * (-posv);
+ view_mat.block <3, 1> (0, 3).noalias() = view_mat.topLeftCorner<3, 3> () * (-posv);
}
///////////////////////////////////////////////////////////////////////
field_data->SetFieldData (field_values);
renwinupd->xy_plot_->AddDataObjectInput (field_data);
- renwinupd->ren_->AddActor2D (renwinupd->xy_plot_);
+ renwinupd->ren_->AddViewProp (renwinupd->xy_plot_);
renwinupd->xy_plot_->SetYTitle (""); renwinupd->xy_plot_->SetXTitle ("");
renwinupd->xy_plot_->SetYRange (min_max[0], min_max[1]);
renwinint.xy_plot_->SetWidth (1); renwinint.xy_plot_->SetHeight (1);
// Create the new window with its interactor and renderer
- renwinint.ren_->AddActor2D (renwinint.xy_plot_);
+ renwinint.ren_->AddViewProp (renwinint.xy_plot_);
renwinint.ren_->SetBackground (1, 1, 1);
renwinint.win_->SetWindowName (id.c_str ());
renwinint.win_->AddRenderer (renwinint.ren_);
if ((eventid == vtkCommand::LeftButtonPressEvent) && (iren->GetShiftKey () > 0))
{
float x = 0, y = 0, z = 0;
- int idx = performSinglePick (iren, x, y, z);
+ const auto idx = performSinglePick (iren, x, y, z);
// Create a PointPickingEvent if a point was selected
if (idx != pcl::UNAVAILABLE)
{